use warnings;
use strict;


my $dbh = &Get_Db;
my $wh = &Get_Watch;	
my $menu = &HtmlMenu(0);
my $new_page = 0;
my $max_nzbs = 99;
if ($VAR{'MaxNzbs'}){ $max_nzbs = $VAR{'MaxNzbs'}; }
unless ($VAR{'NS_Key'}){ $VAR{'NS_Key'} = ''; }
unless ($VAR{'NI_Key'}){ $VAR{'NI_Key'} = ''; }
unless ($VAR{'PN_Key'}){ $VAR{'PN_Key'} = ''; }
unless ($VAR{'NT_Key'}){ $VAR{'NT_Key'} = ''; }
unless ($VAR{'KS_Key'}){ $VAR{'KS_Key'} = ''; }
unless ($VAR{'DN_Key'}){ $VAR{'DN_Key'} = ''; }

# my %Nn_cats = (
# 		'-2' => 'My-Cart', '-3' => 'My-Shows', '-4' => 'My-Movies',
# 
# 		1000 => 'Console-All', 1010 => 'Console-NDS', 1030 => 'Console-Wii', 1050 => 'Console-Xbox-360', 1080 => 'Console-PS3', 
# 	1020 => 'Console-PSP', 1040 => 'Console-Xbox', 1060 => 'Console-WiiWare-VC', 1070 => 'Console-Xbox-360-DLC',
# 		
# 		2000 => 'Movies-All', 2010 => 'Movies-Foreign', 2020 => 'Movies-Other', 2030 => 'Movies-SD', 2040 => 'Movies-HD',
# 		2050 => 'Movies-BluRay', 	 2060 => 'Movies-3D', 
# 		
# 		5000 => 'TV-All', 5070 => 'TV-Anime', 5020 => 'TV-Foreign', 5040 => 'TV-HD', 5050 => 'TV-Other', 5030 => 'TV-SD', 5060 => 'TV-Sport',
# 		5080 => 'TV-Documentary', 
# 		3000 => 'Audio-All', 3030 => 'Audio-Audiobook', 3040 => 'Audio-Lossless', 3010 => 'Audio-MP3', 3020 => 'Audio-Video', 
# 		4000 => 'PC-All', 4010 => 'PC-0day', 4050 => 'PC-Games', 4020 => 'PC-ISO', 4030 => 'PC-Mac', 
# 		4070 => 'PC-Mobile-Android', 4040 => 'PC-Mobile-Other', 4060 => 'PC-Mobile-iOS',
# 		6000 => 'XXX-All', 6010 => 'XXX-DVD', 6020 => 'XXX-WMV', 6030 => 'XXX-XviD', 6040 => 'XXX-x264', 
# 		6050 => 'XXX-Pack', 6060 => 'XXX-ImgSet',  
# 		7000 => 'Other-All', 7030 => 'Other-Comics', 7020 => 'Other-Ebook', 7010 => 'Other-Misc',
# )
my %Sites = (
	Nzbsorg => {
		XX => 'NO', page => 'http://nzbs.org/browse?t=', nzb => 'http://nzbs.org/getnzb/',
		s_kw => 'http://nzbs.org/search/', s_cat => '/?t=', s_tail => '',
		'SR_TV' => 5030, 'HR_TV' => 5040, 'SR_VD' => 2030, 'HR_VD' => 2040,

# 		XX => 'NO', page => 'http://nzbs.org/rss?num=50&dl=1&i=6021&r='.$VAR{'NO_Key'}.'&t=', nzb => 'http://nzbs.org/getnzb/',
# 		s_kw => 'http://nzbs.org/api?t=search&extended=1&q=',  s_cat => '&cat=', s_tail =>'&apikey='.$VAR{'NO_Key'},
		'TV' => $VAR{'NO_TV'}, 'Movies' => $VAR{'NO_Movies'}, Other => $VAR{'NO_Other'},
		#$VAR{'NO_TV'} => 'TV', $VAR{'NO_Movies'} => 'Movies', $VAR{'NO_Other'} => 'Other', 
		'-2' => 'My-Cart', '-3' => 'My-Shows', '-4' => 'My-Movies',

		1000 => 'Console-All', 1010 => 'Console-NDS', 1030 => 'Console-Wii', 1050 => 'Console-Xbox-360', 1080 => 'Console-PS3', 
	1020 => 'Console-PSP', 1040 => 'Console-Xbox', 		1090 =>'Console-PS2', 
		
		2000 => 'Movies-All', 2010 => 'Movies-DVD', 2020 => 'Movies-WMV-HD', 2030 => 'Movies-XviD', 2040 => 'Movies-x264', 
		2050 => 'Movies-Other', 	 2060 => 'Movies-Foreign', 2070 => 'Movies-3D', 
		
		3000 => 'Music-All', 3040 => 'Music-FLAC', 3010 => 'Music-MP3', 3020 => 'Music-Video', 
	4000 => 'Apps-All', 4010 => 'Apps-0day', 4050 => 'Apps-Ebook', 4020 => 'Apps-ISO', 4030 => 'Apps-Mac', 4040 => 'Apps-Phone', 
	4060 => 'Apps-IOS', 4070 => 'Apps-Android', 
		
		5000 => 'TV-All', 5010 => 'TV-DVD', 5030 => 'TV-SD', 5040 => 'TV-HD', 5060 => 'TV-Other', 
		5070 => 'TV-BoxSD', 5080 => 'TV-Foreign', 5090 => 'TV-BoxHD', 
		
		6000 => 'XXX-All', 6010 => 'XXX-DVD', 6020 => 'XXX-Clip', 6030 => 'XXX-XviD', 6040 => 'XXX-x264', 
		6050 => 'XXX-Pack', 6060 => 'XXX-IMGSET', 
		 
		7000 => 'Other', 7010 => 'Other-Misc',
	},
	Nzbsu => {
		XX => 'NS', page => 'http://www.nzb.su/rss?num=50&dl=1&i=60205&r='.$VAR{'NS_Key'}.'&t=', nzb => 'http://www.nzb.su/getnzb/',
		rss => 'http://www.nzb.su/rss?num=25&dl=1&i=60205&r='.$VAR{'NS_Key'}.'&t=',
		#XX => 'NS', page => 'http://www.nzb.su/api?t=search&limit=50&extended=1&apikey='.$VAR{'NS_Key'}.'&cat=', nzb => 'http://www.nzb.su/getnzb/',
		s_kw => 'http://www.nzb.su/api?t=search&limit=50&extended=1&q=',  s_cat => '&cat=', s_tail =>'&apikey='.$VAR{'NS_Key'},
		'TV' => $VAR{'NS_TV'}, 'Movies' => $VAR{'NS_Movies'}, Other => $VAR{'NS_Other'},
		#$VAR{'NS_TV'} => 'TV', $VAR{'NS_Movies'} => 'Movies', $VAR{'NS_Other'} => 'Other', 
		'-2' => 'My-Cart', '-3' => 'My-Shows', '-4' => 'My-Movies',

		1000 => 'Console-All', 1010 => 'Console-NDS', 1030 => 'Console-Wii', 1050 => 'Console-Xbox-360', 1080 => 'Console-PS3', 
	1020 => 'Console-PSP', 1040 => 'Console-Xbox', 1060 => 'Console-WiiWare-VC', 1070 => 'Console-Xbox-360-DLC',
		
		2000 => 'Movies-All', 2010 => 'Movies-Foreign', 2020 => 'Movies-Other', 2030 => 'Movies-SD', 2040 => 'Movies-HD',
		2050 => 'Movies-BluRay', 	 2060 => 'Movies-3D', 
		
		3000 => 'Audio-All', 3030 => 'Audio-Audiobook', 3040 => 'Audio-Lossless', 3010 => 'Audio-MP3', 3020 => 'Audio-Video', 
		4000 => 'PC-All', 4010 => 'PC-0day', 4050 => 'PC-Games', 4020 => 'PC-ISO', 4030 => 'PC-Mac', 
		4070 => 'PC-Mobile-Android', 4040 => 'PC-Mobile-Other', 4060 => 'PC-Mobile-iOS',
		
		5000 => 'TV-All', 5070 => 'TV-Anime', 5020 => 'TV-Foreign', 5040 => 'TV-HD', 5050 => 'TV-Other', 5030 => 'TV-SD', 5060 => 'TV-Sport',
		5080 => 'TV-Documentary', 

		6000 => 'XXX-All', 6010 => 'XXX-DVD', 6020 => 'XXX-WMV', 6030 => 'XXX-XviD', 6040 => 'XXX-x264', 
		6050 => 'XXX-Pack', 6060 => 'XXX-ImgSet',  
		7000 => 'Other-All', 7030 => 'Other-Comics', 7020 => 'Other-Ebook', 7010 => 'Other-Misc',
	},
	Pwnzb => {
		XX => 'PN', page => 'http://pwnzb.com/rss?num=50&dl=1&i=3156&r='.$VAR{'PN_Key'}.'&t=', nzb => 'http://pwnzb.com/getnzb/',
		rss => 'http://pwnzb.com/rss?num=25&dl=1&i=3156&r='.$VAR{'PN_Key'}.'&t=',
		s_kw => 'http://pwnzb.com/api?t=search&limit=50&extended=1&q=',  s_cat => '&cat=', s_tail =>'&apikey='.$VAR{'PN_Key'},
		'TV' => $VAR{'PN_TV'}, 'Movies' => $VAR{'PN_Movies'}, Other => $VAR{'PN_Other'},
		'-2' => 'My-Cart', '-3' => 'My-Shows', '-4' => 'My-Movies',

		1000 => 'Console-All', 1010 => 'Console-NDS', 1030 => 'Console-Wii', 1050 => 'Console-Xbox-360', 1080 => 'Console-PS3', 
	1020 => 'Console-PSP', 1040 => 'Console-Xbox', 1060 => 'Console-WiiWare-VC', 1070 => 'Console-Xbox-360-DLC',
		
		2000 => 'Movies-All', 2010 => 'Movies-Foreign', 2020 => 'Movies-Other', 2030 => 'Movies-SD', 2040 => 'Movies-HD',
		2050 => 'Movies-BluRay', 	 2060 => 'Movies-3D', 
		
		3000 => 'Audio-All', 3030 => 'Audio-Audiobook', 3040 => 'Audio-Lossless', 3010 => 'Audio-MP3', 3020 => 'Audio-Video', 
		4000 => 'PC-All', 4010 => 'PC-0day', 4050 => 'PC-Games', 4020 => 'PC-ISO', 4030 => 'PC-Mac', 
		4070 => 'PC-Mobile-Android', 4040 => 'PC-Mobile-Other', 4060 => 'PC-Mobile-iOS',
		
		5000 => 'TV-All', 5070 => 'TV-Anime', 5020 => 'TV-Foreign', 5040 => 'TV-HD', 5050 => 'TV-Other', 5030 => 'TV-SD', 5060 => 'TV-Sport',
		5080 => 'TV-Documentary', 
		
		6000 => 'XXX-All', 6010 => 'XXX-DVD', 6020 => 'XXX-WMV', 6030 => 'XXX-XviD', 6040 => 'XXX-x264', 
		6050 => 'XXX-Pack', 6060 => 'XXX-ImgSet',  
		7000 => 'Other-All', 7030 => 'Other-Comics', 7020 => 'Other-Ebook', 7010 => 'Other-Misc',
	},
	Nzbtv => {
		XX => 'NT', page => 'http://nzbtv.net/rss?num=50&dl=1&i=12958&r='.$VAR{'NT_Key'}.'&t=', nzb => 'http://nzbtv.net/getnzb/',
		rss => 'http://nzbtv.net/rss?num=25&dl=1&i=12958&r='.$VAR{'NT_Key'}.'&t=',
		s_kw => 'http://nzbtv.net/api?t=search&limit=50&extended=1&q=',  s_cat => '&cat=', s_tail =>'&apikey='.$VAR{'NT_Key'},
		'TV' => $VAR{'NT_TV'}, 'Movies' => $VAR{'NT_Movies'}, Other => $VAR{'NT_Other'},
		'-2' => 'My-Cart', '-3' => 'My-Shows', '-4' => 'My-Movies',

		1000 => 'Console-All', 1010 => 'Console-NDS', 1030 => 'Console-Wii', 1050 => 'Console-Xbox-360', 1080 => 'Console-PS3', 
	1020 => 'Console-PSP', 1040 => 'Console-Xbox', 1060 => 'Console-WiiWare-VC', 1070 => 'Console-Xbox-360-DLC',
		
		2000 => 'Movies-All', 2010 => 'Movies-Foreign', 2020 => 'Movies-Other', 2030 => 'Movies-SD', 2040 => 'Movies-HD',
		2050 => 'Movies-BluRay', 	 2060 => 'Movies-3D', 
		
		3000 => 'Audio-All', 3030 => 'Audio-Audiobook', 3040 => 'Audio-Lossless', 3010 => 'Audio-MP3', 3020 => 'Audio-Video', 
		4000 => 'PC-All', 4010 => 'PC-0day', 4050 => 'PC-Games', 4020 => 'PC-ISO', 4030 => 'PC-Mac', 
		4070 => 'PC-Mobile-Android', 4040 => 'PC-Mobile-Other', 4060 => 'PC-Mobile-iOS',
		
		5000 => 'TV-All', 5070 => 'TV-Anime', 5020 => 'TV-Foreign', 5040 => 'TV-HD', 5050 => 'TV-Other', 5030 => 'TV-SD', 5060 => 'TV-Sport',
		5080 => 'TV-Documentary', 
		
		6000 => 'XXX-All', 6010 => 'XXX-DVD', 6020 => 'XXX-WMV', 6030 => 'XXX-XviD', 6040 => 'XXX-x264', 
		6050 => 'XXX-Pack', 6060 => 'XXX-ImgSet',  
		7000 => 'Other-All', 7030 => 'Other-Comics', 7020 => 'Other-Ebook', 7010 => 'Other-Misc',
	},
	Nzbsin => {
		XX => 'NI', page => 'http://nzbs.in/rss?num=50&dl=1&i=3705&r='.$VAR{'NI_Key'}.'&t=', nzb => 'http://nzbs.in/getnzb/',
		rss => 'http://nzbs.in/rss?num=25&dl=1&i=3705&r='.$VAR{'NI_Key'}.'&t=',
		s_kw => 'http://nzbs.in/api?t=search&limit=50&extended=1&q=',  s_cat => '&cat=', s_tail =>'&apikey='.$VAR{'NI_Key'},
		'TV' => $VAR{'NI_TV'}, 'Movies' => $VAR{'NI_Movies'}, Other => $VAR{'NI_Other'},
		#$VAR{'NI_TV'} => 'TV', $VAR{'NI_Movies'} => 'Movies', $VAR{'NI_Other'} => 'Other', 
		'-2' => 'My-Cart', '-3' => 'My-Shows', '-4' => 'My-Movies',

		1000 => 'Console-All', 1010 => 'Console-NDS', 1030 => 'Console-Wii', 1050 => 'Console-Xbox-360', 1080 => 'Console-PS3', 
	1020 => 'Console-PSP', 1040 => 'Console-Xbox', 1060 => 'Console-WiiWare-VC', 1070 => 'Console-Xbox-360-DLC',
		
		2000 => 'Movies-All', 2010 => 'Movies-Foreign', 2020 => 'Movies-Other', 2030 => 'Movies-SD', 2040 => 'Movies-HD',
		2050 => 'Movies-BluRay', 	 2060 => 'Movies-3D', 
		
		3000 => 'Audio-All', 3030 => 'Audio-Audiobook', 3040 => 'Audio-Lossless', 3010 => 'Audio-MP3', 3020 => 'Audio-Video', 
		4000 => 'PC-All', 4010 => 'PC-0day', 4050 => 'PC-Games', 4020 => 'PC-ISO', 4030 => 'PC-Mac', 
		4070 => 'PC-Mobile-Android', 4040 => 'PC-Mobile-Other', 4060 => 'PC-Mobile-iOS',
		
		5000 => 'TV-All', 5070 => 'TV-Anime', 5020 => 'TV-Foreign', 5040 => 'TV-HD', 5050 => 'TV-Other', 5030 => 'TV-SD', 5060 => 'TV-Sport',
		5080 => 'TV-Documentary', 

		6000 => 'XXX-All', 6010 => 'XXX-DVD', 6020 => 'XXX-WMV', 6030 => 'XXX-XviD', 6040 => 'XXX-x264', 
		6050 => 'XXX-Pack', 6060 => 'XXX-ImgSet',  
		7000 => 'Other-All', 7030 => 'Other-Comics', 7020 => 'Other-Ebook', 7010 => 'Other-Misc',
	},
	Dognzb => {
		#XX => 'DN', page => 'http://dognzb.cr/rss.cfm?num=50&r='.$VAR{'DN_Key'}.'&t=', nzb => 'http://www.dognzb.cr/fetch/',
		rss => 'http://dognzb.cr/rss.cfm?num=25&r='.$VAR{'DN_Key'}.'&t=', 
		XX => 'DN', page => 'http://dognzb.cr/api.cfm?t=search&limit=50&extended=1&apikey='.$VAR{'DN_Key'}.'&cat=', nzb => 'http://www.dognzb.cr/fetch/',
		s_kw => 'http://dognzb.cr/api.cfm?t=search&limit=50&extended=1&q=',  s_cat => '&cat=', s_tail =>'&apikey='.$VAR{'DN_Key'},
		'TV' => $VAR{'DN_TV'}, 'Movies' => $VAR{'DN_Movies'}, Other => $VAR{'DN_Other'},
		#$VAR{'DN_TV'} => 'TV', $VAR{'DN_Movies'} => 'Movies', $VAR{'DN_Other'} => 'Other', 
		
		1000 => 'Console-All', 1010 => 'Console-NDS', 1080 => 'Console-PS3', 1030 => 'Console-Wii', 1050 => 'Console-Xbox-360', 
		
		2000 => 'Movies-All', 2010 => 'Movies-Foreign', 2040 => 'Movies-HD', 2020 => 'Movies-Other', 2030 => 'Movies-SD', 
		2050 => 'Movies-BluRay', 	 2060 => 'Movies-3D', 
		
		3000 => 'Audio-All', 3030 => 'Audio-Audiobook', 3040 => 'Audio-Lossless', 3010 => 'Audio-MP3', 3020 => 'Audio-Video', 
		4000 => 'PC-All', 4010 => 'PC-0day', 4050 => 'PC-Games', 4020 => 'PC-ISO', 4030 => 'PC-Mac', 
		4070 => 'PC-Mobile-Android', 4040 => 'PC-Mobile-Other', 4060 => 'PC-Mobile-iOS', 
		
		5000 => 'TV-All', 5070 => 'TV-Anime', 5020 => 'TV-Foreign', 5040 => 'TV-HD', 5050 => 'TV-Other', 5030 => 'TV-SD', 5060 => 'TV-Sport', 
		5080 => 'TV-Documentary', 
		
		6000 => 'XXX-All', 6010 => 'XXX-DVD', 6020 => 'XXX-WMV', 6030 => 'XXX-XviD', 6040 => 'XXX-x264', 
		6050 => 'XXX-Pack', 6060 => 'XXX-ImgSet',  
		7000 => 'Other-All', 7030 => 'Other-Comics', 7020 => 'Other-Ebook', 7010 => 'Other-Misc', 
	9000 => 'My-Cart',

	},
);

if ($VAR{'NO_Key'}){ # &rlsdate=2
	my $filters = '';
	if ($VAR{'NO_res'} and $VAR{'NO_res'} =~ m! *(\d+) *!){
		$filters .= '&res='.$1;
		$filters =~ s!&res=(\d)(\d)!&res=$1,$2!;
	}
	if ($VAR{'NO_fmt'} and $VAR{'NO_fmt'} =~ m! *(\d,?\d?) *!){
		$filters .= '&fmt='.$1;
	}
	if ($VAR{'NO_min'} and $VAR{'NO_min'} =~ m! *(\d{2,3}) *!){
		$filters .= '&minsize='.$1;
	}
	if ($VAR{'NO_max'} and $VAR{'NO_max'} =~ m! *(\d{3,5}) *!){
		$filters .= '&maxsize='.$1;
	}
	$Sites{'Nzbsorg'}{'rss'} = 'http://nzbs.org/rss?num=25&dl=1&i=6021&r='.$VAR{'NO_Key'}.'&t=';
	#Video resolution (SD=1, HD=2, HD+=3), supports multiple resolutions : &res=2 | &res=2,3 
	#Video format (XviD=1, x264=2, h264=3), supports multiple formats: &fmt=2 | &fmt=2,3
	#Minimum size (in MB): &minsize=100 (100MB) 
	#Maximum size (in MB): &maxsize=7000 (7GB)
	#$Sites{'Nzbsorg'}{'page'} = 'http://nzbs.org/api?t=search&limit=50&extended=1&fmt=1,2&maxsize=5000&apikey='.$VAR{'NO_Key'}.'&cat=';
	$Sites{'Nzbsorg'}{'page'} = 'http://nzbs.org/api?t=search&limit=50&extended=1'.$filters.'&apikey='.$VAR{'NO_Key'}.'&cat=';
	$Sites{'Nzbsorg'}{'s_kw'} = 'http://nzbs.org/api?t=search&limit=50&extended=1'.$filters.'&q=';
	#$Sites{'Nzbsorg'}{'s_kw'} = 'http://nzbs.org/api?t=search&q=';
	$Sites{'Nzbsorg'}{'s_cat'} = '&cat=';
	$Sites{'Nzbsorg'}{'s_tail'} = '&apikey='.$VAR{'NO_Key'};
# 	delete $Sites{'Nzbsorg'}{'SR_TV'};
# 	delete $Sites{'Nzbsorg'}{'HR_TV'};
# 	delete $Sites{'Nzbsorg'}{'SR_VD'};
# 	delete $Sites{'Nzbsorg'}{'HR_VD'};
}


my %Vid_Qual = (
	WV => 'WMV',
	BD => 'BLURAY|BD25|BD50',
	DD => 'DVD[59]|M?DVDr|BR2DVD',
	HD => 'HD[ .-]?D(?:VD)?|M?B[DR][. -]?RIP|(?:HD)?DVD[. -]?RIP|BR5|M?Blu[ .-]?Ray',
	DR => 'HD[ .-]?D(?:VD)?|B[DR][. -]?RIP|(?:HD)?DVD[. -]?RIP',
	SD => 'HD[ .-]?D(?:VD)?|B[DR][. -]?RIP|(?:HD)?DVD[. -]?RIP',
	R5 => 'B[DR][. -]?RIP|DVD[. -]?RIP|R[C2456]',
	SC => '[HBT][DRV][. -]?RIP|DVD[. -]?(?:RIP|SCR)|R[C2456]|(?:S|HD)TV(?:RIP)?|[VWP][OEP][DBV][ -]?(?:Rip|DL)|SCR(?:EENER|[ -]?RIP)?',

# 	R5 => 'R[C2456]',
# 	VD => '[VWP][OEP][DBV][ -]?Rip|[HT][DV]DRip',
# 	SC => 'DVD[. -]?SCR|SCR(?:EENER|[ -]?RIP)?',
# 	TC => '(?:HD)?TC|TELECINE',
# 	TS => '(?:HD)?TS|TELESYNC',
# 	CM => '(?:HD)?CAM',
	
	TC => '[HBT][DRV][. -]?RIP|DVD[. -]?(?:RIP|SCR)|R[C2456]|(?:S|HD)TV(?:RIP)?|[VWP][OEP][DBV][ -]?(?:Rip|DL)|SCR(?:EENER|[ -]?RIP)?|(?:HD)?TC|TELECINE',
	TS => '[HBT][DRV][. -]?RIP|DVD[. -]?(?:RIP|SCR)|R[C2456]|(?:S|HD)TV(?:RIP)?|[VWP][OEP][DBV][ -]?(?:Rip|DL)|SCR(?:EENER|[ -]?RIP)?|(?:HD)?TC|TELECINE|(?:HD)?TS|TELESYNC',
	CM => '[HBT][DRV][. -]?RIP|DVD[. -]?(?:RIP|SCR)|R[C2456]|(?:S|HD)TV(?:RIP)?|[VWP][OEP][DBV][ -]?(?:Rip|DL)|SCR(?:EENER|[ -]?RIP)?|(?:HD)?TC|TELECINE|(?:HD)?TS|TELESYNC|(?:HD)?CAM(?:RIP)?',
	SR => 'SR',
	SX => 'x264',
	SA => 'B[DR][. -]?RIP|(?:HD)?DVD[. -]?RIP',
	H7 => 'H7',
	H1 => 'H1',
	HR => 'HR',
	AL => 'AL',
	HS => 'HR|H7|H1|SR|SX',
	AT => 'AT',
);

# site cat > XX res, only needed for TV?
my %XX_res = (
	'XviD' => 'SR', 'X264' => 'SR', 'SD' => 'SR', 'SR' => 'SR', 'TV-SD' => 'SR', 'TV-XviD' => 'SR', 'TV-x264' => 'SR', 'BoxSD' => 'SR', 
	'720p' => 'HR', '1080p' => 'HR', 'HD' => 'HR', 'HR' => 'HR', 'TV-HD' => 'HR', 'BoxHD' => 'HR', 
	'Custom' => $VAR{'NR_Custom'}, 
);

sub Update_Sites {
	my @sites;
	if ($VAR{'SiteOrder'}){
		@sites = split (/\|/, $VAR{'SiteOrder'});
	}
	else { @sites = ('Nzbsorg', 'Nzbsu', 'Nzbsin', 'Pwnzb', 'Nzbtv', 'Dognzb'); }
	foreach my $site (@sites){
		if ($VAR{$Sites{$site}{'XX'}.'_Enable'}){
			&Update_Site ($site);
		}
	}
	if ($new_page){ &HtmlMenu(1); }
# 	if ($VAR{'NzbgetRev'} and $VAR{'NzbgetRev'} > 507 and $VAR{'NzbTrim'}){
# 		system qx($VAR{'NzbgetRun'} -E FR P \"[_.-]\($VAR{'NzbTrim'}\)\(\b|_|\.|-\)\" > /dev/null);
# 	}
}

sub Update_Site {
	my ($site) = @_;
	my $found = 0;
	if ($site eq 'Nzbsorg' and $VAR{'NO_Key'}){
		require $VAR{'LibDir'}.'/Newznab.pm';
	}
	elsif ($site eq 'Nzbsu' or $site eq 'Dognzb' or $site eq 'Nzbsin' or $site eq 'Pwnzb' or $site eq 'Nzbtv',){
		unless (require $VAR{'LibDir'}.'/Newznab.pm'){
			&Print ("  require $VAR{'LibDir'}/Newznab.pm failed, $! (USL)", 1, 0); 
		}
		#require $VAR{'LibDir'}.'/Newznab.pm';
	}
	else { 
		unless (require $VAR{'LibDir'}.'/'.$site.'.pm'){
			&Print ("  require $VAR{'LibDir'}/$site.pm failed, $! (USL)", 1, 0); 
		}
	}
	# &Update_Page site cat_num resolution cat_name
	if($VAR{$Sites{$site}{'XX'}.'_SR_TV'}){
		&Update_Page ($site, $Sites{$site}{'SR_TV'}, $Vid_Qual{'SR'}, $Sites{$site}{$Sites{$site}{'SR_TV'}}, 'Tv');
		$found ++;
	}
	if($VAR{$Sites{$site}{'XX'}.'_SX_TV'}){  
		&Update_Page ($site, $Sites{$site}{'SX_TV'}, $Vid_Qual{'SR'}, 'TV-x264', 'Tv');
		$found ++;
	}
	if($VAR{$Sites{$site}{'XX'}.'_HR_TV'}){  
		&Update_Page ($site, $Sites{$site}{'HR_TV'}, $Vid_Qual{'HR'}, 'TV-HD', 'Tv');
		$found ++;
	}
	if($VAR{$Sites{$site}{'XX'}.'_SR_VD'}){ 
		my $res = $VAR{$Sites{$site}{'XX'}.'_SR_VD'};
		&Update_Page ($site, $Sites{$site}{'SR_VD'}, $Vid_Qual{$res}, 'Movies-XviD', 'Vid');
		$found ++;
	}
	if($VAR{$Sites{$site}{'XX'}.'_HR_VD'}){  
		my $res = $VAR{$Sites{$site}{'XX'}.'_HR_VD'};
		&Update_Page ($site, $Sites{$site}{'HR_VD'}, $Vid_Qual{$res}, 'Movies-HD', 'Vid');
		$found ++;
	}
	if($VAR{$Sites{$site}{'XX'}.'_Custom'}){  
		&Update_Page ($site, $Sites{$site}{'Custom'}, '', 'Custom', '');
		$found ++;
	}
	# newznab TV, VD, OT
	if($VAR{$Sites{$site}{'XX'}.'_TV'}){
		$Sites{$site}{'TV'} =~ s!\|!,!g; # > comma separated list
		&Update_Page ($site, $Sites{$site}{'TV'}, '', 'TV', 'Tv');
		$found ++;
	}
	if($VAR{$Sites{$site}{'XX'}.'_Movies'}){
		$Sites{$site}{'Movies'} =~ s!\|!,!g;
		&Update_Page ($site, $Sites{$site}{'Movies'}, '', 'Movies', 'Vid');
		$found ++;
	}
	if($VAR{$Sites{$site}{'XX'}.'_Other'}){
		my @other = split (/\|/, $VAR{$Sites{$site}{'XX'}.'_Other'});
		foreach my $cat_num (@other){
# 			if ($cat_num =~ m!(.+):(.+)!){ # specify cat_name or ?, not using yet
# 				&Update_Page ($site, $1, '', $2);
# 			}
# 			else {
				&Update_Page ($site, $cat_num, '', $Sites{$site}{$cat_num}, '');
				$found ++;
			#}
		}
	}
	# don't have $cgi, maybe I should - see wfnzb.cgi &Update_Site ($site) calls (2)
# 	if (-e $VAR{'HtmlDir'}.'/'.$site.'_'.$VAR{$Sites{$site}{'XX'}.'_Default'}.'.html'){
# 		print $cgi->redirect($VAR{'Protocol'}.$VAR{'Host'}.$VAR{'HtmlUrl'}.'/'.$site.'_'.$VAR{$Sites{$site}{'XX'}.'_Default'}.'.html');
# 	}
# 	else { print $cgi->redirect($VAR{'Protocol'}.$VAR{'Host'}.$VAR{'HomeUrl'}); }
	unless ($found){ &Print ("  No enabled categories found for $site (USC)", 1, 0); }
}

sub Update_Page {
	my ($site, $cat_num, $res, $cat_name, $type) = @_; # $cat_num(s)
	&Print ('Updating '.$site.' '.$cat_name.' (UP01)', 4, 0);
	if ($res and $res !~ m!\|!){ # single page update VS site update which already has res
		$res = $Vid_Qual{$res}; # to accommodate SR/HR > SD/SR
	}
	my $user_agent = &GetUA ($site, 0);
	my @page;
	if ($cat_name =~ m!^My! or $cat_num =~ m!^-!){ # Always RSS and not searchable
		if ($cat_name =~ m!Cart!){ $Sites{$site}{'rss'} =~ s!\&dl\=1!&dl=1&del=1!; }
		@page = &FetchUrl($site, $Sites{$site}{'rss'}.$cat_num, $user_agent);
	}
	else { @page = &FetchUrl($site, $Sites{$site}{'page'}.$cat_num, $user_agent); }
	if (@page){
		my ($sh, $free, $new_nzbs, $max_nzbs, $message) = &ParsePage (\@page, $cat_name, $user_agent, $site, $type, $max_nzbs);
		if ($sh){
			if ($VAR{$Sites{$site}{'XX'}.'_Default'}){ # if set, write html page
				if ($message){
					#&Print ('  Have message (UPM)', 5, 0);
					$message = "$DateTime[0] fetches:<br>$message";
				}
				my (@new_nzbs) = &Write_New ($sh, $site, $cat_num, $VAR{$Sites{$site}{'XX'}.'_Default'}, $free, $menu, '', $cat_name, $message); # no kw
				#if ($new_cnt){ &UpdateIndex ($new_cnt, @new_nzbs); }
			}
			if ($new_nzbs){ # number of new nzbs
				#$max_nzbs = $max_nzbs - $new_nzbs; # because only $new_nzbs pass circuit is complete (even though $max_nzbs is gloabal here)
				# won't work, nzbs may not be queued yet
# 				if ($VAR{'NzbgetRev'} and $VAR{'NzbgetRev'} > 507 and $VAR{'NzbTrim'} and $site ne 'Nzbmatrix' and $site ne 'Nzbsrus' and ($VAR{'NO_Key'} or $site ne 'Nzbsorg')){
# 					&Print ("  Sending pause command for NzbTrim matches (UP01)", 5, 0);
# 					my $r = "[_.-]($VAR{'NzbTrim'})(\b|_|\.|-)";
# 					system qx($VAR{'NzbgetRun'} -E FR P $r > /dev/null);
# 				}
				if ($free and $free < 11){ 
					# edit free count on default page 
					if ($VAR{$Sites{$site}{'XX'}.'_Default'}){
						# return $free shouldn't change
						$free = &UpdateCount ($site.'_'.$VAR{$Sites{$site}{'XX'}.'_Default'}, $new_nzbs);
					}
					&Print ("Got $new_nzbs $site $cat_name nzbs ($free left) (UP01)", 3, 0);
				}
				else { &Print ("Got $new_nzbs $site $cat_name nzbs ($max_nzbs left) (UP01)", 3, 0); }
				
			}
			else { &Print ("Updated $site $cat_name - no new nzb's (UP01)", 3, 0); }
			# non watchlist page update... newznab only?
			#else { &Print ("Updated $site $cat_name (UP01)", 3, 0); }
		}
		else { &Print ("Content parse failure, $site $cat_name not updated (UP01)", 1, 0); }
	}
	else { &Print ("No content to parse, $site $cat_name not updated (UP01)", 1, 0); }
}

sub Search_Page {
	my ($site, $cgi) = @_;
	my $user_agent = &GetUA ($site, 0);

	my $cat_name;
	my $type;
 	if ($cgi->param('cn') eq 'TV' or $cgi->param('cn') eq 'Movies'){
		$Sites{$site}{$cgi->param('cn')} =~ s!\|!,!g;
		# want to use $cgi->param('cn') if multiple cats (site hash cn = sc), but
		# eq fails if configuration is changed and update not run before search/browse
		if ($Sites{$site}{$cgi->param('cn')} eq $cgi->param('sc')){ # 'XX_Movies' = nun,num = num,num
			$cat_name = $cgi->param('cn');
		}
		# and $cat_name will be empty if eq fails and sc contains more than one cat
		# normal single cat translation works fine (we'll have a cat name)
		else { $cat_name = $Sites{$site}{$cgi->param('sc')}; }
		# if $cat_name is empty we know why (failed eq, multi cats) and that its cn (TV|Movies) that the user wants to search/browse
		unless ($cat_name){ $cat_name = $cgi->param('cn'); }

# 		if ($cat_name =~ m!^(TV|Movies)!){
# 			$type = $1;
# 			$type =~ s!TV!Tv!;
# 			$type =~ s!Movies!Vid!;
# 		}
	}
	# normal single cat translation
	else { $cat_name = $Sites{$site}{$cgi->param('sc')}; }
	
	my @page;
	# My-Show, Movies, Cart Always RSS and not searchable
	if ($cat_name =~ m!^My! or $cgi->param('sc') =~ m!^-!){ # -2,3,4 - Dognzb 9000 My-Cart also = Kerews Movies-All
		&Print ('Updating '.$site.' '.$cat_name.' (UP01)', 4, 0);
		if ($cat_name =~ m!Cart!){ $Sites{$site}{'rss'} =~ s!\&dl\=1!&dl=1&del=1!; }
		@page = &FetchUrl($site, $Sites{$site}{'rss'}.$cgi->param('sc'), $user_agent);
	}
	elsif ($cgi->param('kw') and $cgi->param('np')){ # np = next/previous pagination
		&Print ('Searching '.$site.' '.$cat_name.' (UP01)', 4, 0);
		@page = &FetchUrl($site, $Sites{$site}{'s_kw'}.$cgi->param('kw').$Sites{$site}{'s_cat'}.$cgi->param('sc').'&offset='.$cgi->param('np').$Sites{$site}{'s_tail'}, $user_agent);
		$cat_name = 'search_'.$cat_name;
	}
	elsif ($cgi->param('kw')){ # build s_kw, s_cat, s_tail URL
		&Print ('Searching '.$site.' '.$cat_name.' (UP01)', 4, 0);
		@page = &FetchUrl($site, $Sites{$site}{'s_kw'}.$cgi->param('kw').$Sites{$site}{'s_cat'}.$cgi->param('sc').$Sites{$site}{'s_tail'}, $user_agent);
		$cat_name = 'search_'.$cat_name;
	}
	else {
		&Print ('Updating '.$site.' '.$cat_name.' (UP01)', 4, 0);
		@page = &FetchUrl($site, $Sites{$site}{'page'}.$cgi->param('sc'), $user_agent);
	}
	if (@page){
		if ($cat_name =~ m!^(?:My-|search_)?(TV|Movies|Shows)!){
			$type = $1;
			$type =~ s!TV!Tv!;
			$type =~ s!Shows!Tv!;
			$type =~ s!Movies!Vid!;
			#&Print ('My type: '.$type.' my cat name: '.$cat_name.' (UP01)', 4, 0);
		}
		my ($sh, $free, $new_nzbs, $max_nzbs, $message) = &ParsePage (\@page, $cat_name, $user_agent, $site, $type, $max_nzbs);
		if ($sh){
			if ($message){
				#&Print ('  Have message (UPM)', 5, 0);
				$message = "$DateTime[0] fetches:<br>$message";
			}
			&Write_New ($sh, $site, $cgi->param('sc'), $VAR{$Sites{$site}{'XX'}.'_Default'}, $free, $menu, $cgi->param('kw'), $cat_name, $message);
			if ($new_page){ &HtmlMenu(1); }
			if ($new_nzbs){ # number of new nzbs
				#$max_nzbs = $max_nzbs - $new_nzbs; # because only $new_nzbs pass circuit is complete (even though $max_nzbs is gloabal here)
				# won't work, nzbs may not be queued yet
# 				if ($VAR{'NzbgetRev'} and $VAR{'NzbgetRev'} > 507 and $VAR{'NzbTrim'} and $site ne 'Nzbmatrix' and $site ne 'Nzbsrus' and ($VAR{'NO_Key'} or $site ne 'Nzbsorg')){
# 					&Print ("  Sending pause command for NzbTrim matches (UP01)", 5, 0);
# 					my $r = "[_.-]($VAR{'NzbTrim'})(\b|_|\.|-)";
# 					system qx($VAR{'NzbgetRun'} -E FR P $r > /dev/null);
# 				}
				if ($free and $free < 11){ 
					# edit free count on default page 
					if ($VAR{$Sites{$site}{'XX'}.'_Default'}){
						# return $free shouldn't change
						$free = &UpdateCount ($site.'_'.$VAR{$Sites{$site}{'XX'}.'_Default'}, $new_nzbs);
					}
					&Print ("Got $new_nzbs $site $cat_name nzbs ($free left) (UP01)", 3, 0);
				}
				else { &Print ("Got $new_nzbs $site $cat_name nzbs ($max_nzbs left) (UP01)", 3, 0); }
			}
			else { &Print ("Updated $site $cat_name - no new nzb's (UP01)", 3, 0); }
			#&Print ('Updated '.$site.'_'.$cat_name.'.html (US01)', 3, 0);
			print $cgi->redirect($VAR{'Protocol'}.$VAR{'Host'}.$VAR{'HtmlUrl'}.'/'.$site.'_'.$cat_name.'.html');
		}
		else { 
			&Print ('Content parse failure, '.$site.'_'.$cat_name.' not updated (US01)', 1, 0); 
			print $cgi->redirect($VAR{'Protocol'}.$VAR{'Host'}.$VAR{'HomeUrl'});
		}
	}
	else { 
		&Print ('No content to parse, '.$site.'_'.$cat_name.' not updated (US01)', 1, 0); 
		print $cgi->redirect($VAR{'Protocol'}.$VAR{'Host'}.$VAR{'HomeUrl'});
	}
}

sub Get_Watch { 
	# title, real_title, save_title, type(ep/yr = nnn), res(=XX), priority(= +/-nn)
	my $wh = {};
	my $type;
	if ($VAR{'WatchFile'} and -e $VAR{'WatchFile'}){
		open (RLWL, "<$VAR{'WatchFile'}") or &Print ("  Couldn't open $VAR{'WatchFile'}, $! (116)", 1, 1);
		while (<RLWL>){
			chomp;
			# watch type
			if (m!^### (.+)!){
				if ($1 eq 'VIDEO'){ $type = 'yr'; } # to match cat
				elsif ($1 eq 'TV'){ $type = 'ep'; }
				# may want a single type label for everything ###
# 				if ($1 eq 'VIDEO'){ $type = 'Vid'; } # to match cat
# 				elsif ($1 eq 'TV'){ $type = 'Tv'; }
				next;
			}
			elsif (m!^[#\n\r]!){ # commented and empty/last lines
				next;
			}
			# new
			elsif (m!^([^\t]+)\t([^\t]*)\t(\w{2})\t(([^\t]+)\t)?(.*)?!){ # title, ep, res, save
				my $ep_yr = ''; # year or ep
				my $save_title = '';
				#my $alt_cat = '';
				my $priority = '';
				
				# one or more possible listing titles
				my $title = $1;
				# year or ep
				if ($2){ $ep_yr = $2; }
				# XX resolution
				my $res = $3;
				# queue category
				#if ($5){ $alt_cat = $5; }
				if ($4){ $priority = $5; }
				# custom title (doesn't have to be a listing title)
				if ($6){ $save_title = $6; } 
				
				# at least 2 titles - real or alternate and save or alternate
				if ($title =~ m!^([^,]+),!){ 
					# first title (real or listing match)
					my $real_title = $1; 
					# last title = save unless there's a unique 4th field
					unless ($save_title){ $save_title = $real_title; } 
					my @titles = split (/, ?/, $title);
					foreach (@titles){
						# $_ = all possible listing matches
						my $lc_title = lc($_);
						$wh->{$lc_title} = { #real_title,save_title,type,label,cat,res
							title		=> $_,
							real_title	=> $real_title,
							save_title	=> $save_title,
							$type		=> $ep_yr, # yr or ep => nnnn or (n)nnn
							#alt_cat		=> $alt_cat, # optional non default category
							res		=> $res, # XX
							priority	=> $priority,
						};
					}
				}
				else { # we have a single title
					my $lc_title = lc($title);
					$wh->{$lc_title} = {
						title		=> $title,
						real_title	=> $title,
						save_title	=> $title,
						$type		=> $ep_yr,
						#alt_cat		=> $alt_cat,
						res		=> $res,
						priority	=> $priority,
					}
				}
			}
		}
	}
	close RLWL or warn $!;
	return $wh
}

sub Get_Db { 
	# db format is: title (year/ep) \t id \t imdb \t desc
	# db hash is: $dbh->{title}{ep/yr = id, title = title, type = YR|SE|DE|OT }
	# note: the \*? bit used throught is probably not needed, the match issue was elsewhere
	my $dbh = {};
	if ($VAR{'DbFile'} and -e $VAR{'DbFile'}){
		open (RDB, "<$VAR{'DbFile'}") or &Print ("  Couldn't open $VAR{'DbFile'}, $! (117)", 1, 1);
		while (<RDB>){
			# Title has year label note: nothing after year to help prevent episode matches (which typically have sub labels)
			if (m!^([^\t]+) (19[3-9]\d|20[01]\d)\t([^\t]+\*?)?\t!){
				my $lc_title = lc($1);
				my $id = '';
				if ($3){ $id = $3; }
				# existing hash - if db title and db title type = yr
				if ($dbh->{$lc_title} and $dbh->{$lc_title}{'type'} eq 'YR'){ ### use type field (yr SE sN eN pN sD eD) with ep/yr => id fields
					if ($id){ # set so can test if ($db_hh->{$lc_title}{'yr'}{$year})?... or $db_hh->{$lc_title}{'ep'}{$ep}
						# if  ($db_hh->{$lc_title}{$year}){ Db has $lc_title $year match ('1' or $id)
						# 	if  ($db_hh->{$lc_title}{$year} ne '1'){ $lc_title .= $db_hh->{$lc_title}{$year}; }
						# 	'1' matches and test allows $lc_title VS $lc_title ($id) when printing Db has
						# db title year = id
						$dbh->{$lc_title}{$2} = $id;
					} # db title year = 1
					else { $dbh->{$lc_title}{$2} = 1; } # need true value???
				}
				# new hash
				else { # new db title
					if ($id){ $dbh->{$lc_title}{$2} = $id; }
					else { $dbh->{$lc_title}{$2} = 1; }
					$dbh->{$lc_title}{'title'} = $1; # actual db title (not lc)
					$dbh->{$lc_title}{'type'} = 'YR';
				}
			}
			# Episode range entries (n)nnn-(n)nn - flawed, always nn episodes
			elsif (m!^([^\t]+?) (\d+)(\d{2})-\d?(\d{2})(?: - [^\t]+)?\t([^\t]+\*?)?\t!){
				my $lc_title = lc($1);
				my $s = $2;
				my $first_ep = "$s$3"; # add season
				my $last_ep = "$s$4"; # add season
				my $id = '';
				if ($5){ $id = $5; }
				# existing hash
				if ($dbh->{$lc_title} and $dbh->{$lc_title}{'type'} eq 'SE'){
					if ($id){ $dbh->{$lc_title}{$first_ep} = $id; }
					else {$dbh->{$lc_title}{$first_ep} = 1; }
				}
				# new hash
				else {
					if ($id){ $dbh->{$lc_title}{$first_ep} = $id; } # ep value is id or 1
					else { $dbh->{$lc_title}{$first_ep} = 1; }
					$dbh->{$lc_title}{'title'} = $1; # actual db title (not lc)
					$dbh->{$lc_title}{'type'} = 'SE';
				}
				# add any additional eps (already added first ep)
				while ($first_ep < $last_ep){ 
					$first_ep ++;
					if ($id){ $dbh->{$lc_title}{$first_ep} = $id; }
					else {$dbh->{$lc_title}{$first_ep} = 1; }
				};
			}
			# date based eps and seasons
			elsif (m!^([^\t]+?) (\d{2}-\d{2}-\d{2}|s\d{4})(?: - [^\t]+)?\t([^\t]+\*?)?\t!){
				my $lc_title = lc($1);
				my $id = '';
				if ($3){ $id = $3; }
				if ($dbh->{$lc_title} and $dbh->{$lc_title}{'type'} eq 'DE' ){
					if ($id){ $dbh->{$lc_title}{$2} = $id; }
					else { $dbh->{$lc_title}{$2} = 1; }
				}
				else {
					if ($id){ $dbh->{$lc_title}{$2} = $id; }
					else { $dbh->{$lc_title}{$2} = 1; }
					$dbh->{$lc_title}{'title'} = $1; # actual db title (not lc)
					$dbh->{$lc_title}{'type'} = 'DE';
				}
			}
			# (n)nnn eps and snn(dn) seasons note: nnnn could match year when there's no ep title
			elsif (m!^([^\t]+?) (\d{3,4}|s\d{2}(?:d\d)?)( - [^\t]+)?\t([^\t]+\*?)?\t!){ 
				my $lc_title = lc($1);
				my $id = '';
				if ($4){ $id = $4; }
				if ($dbh->{$lc_title} and $dbh->{$lc_title}{'type'} eq 'SE' ){
					if ($id){ $dbh->{$lc_title}{$2} = $id; }
					else { $dbh->{$lc_title}{$2} = 1; }
				}
				else {
					if ($id){ $dbh->{$lc_title}{$2} = $id; }
					else { $dbh->{$lc_title}{$2} = 1; }
					$dbh->{$lc_title}{'title'} = $1; # actual db title (not lc)
					$dbh->{$lc_title}{'type'} = 'SE';
				}
			}
			# TODO  parts (movies and shows) and eps (shows w/o season)... also need season:disk s04d02
	# 		# single eps, date based eps, seasons, parts, etc.
	# 		elsif (m!^([^\t]+?) (\d{3,4}|\d{2}-\d{2}-\d{2}|(?:s|e|pt)\d{1,4})(?: - [^\t]+)?\t([^\t]*)\t!){
	# 			my $id = '';
	# 			my $lc_title = lc($1);
	# 			my $se = $2; # (n)nnn | nn-nn-nn | (s|e|pt)n(nnn) - ep titles tossed
	# 			my $type;
	# 			if ($se =~ m!\d{2}-\d{2}-\d{2}!){ $type = 'DE'; } # date based ep
	# 			elsif ($se =~ m!s\d{4}!){ $type = 'SY'; } # season year
	# 			elsif ($se =~ m!s\d{2,3}!){ $type = 'SN'; } # season number
	# 			elsif ($se =~ m!pt\d{2,3}!){ $type = 'PN'; } # part number
	# 			elsif ($se =~ m!e\d{2,3}!){ $type = 'EN'; } # ep number
	# 			if ($3){ $id = $3; } # status (could be useful) or other - added to listing db has line
	# 			# add to existing hash unless its a movie - has a year entry
	# 			if ($dbh->{$lc_title} and !$dbh->{$lc_title}{'yr'}){
	# 				# if existing hash has an episode entry
	# 				if ($dbh->{$lc_title}{'ep'}){
	# 					# if new item is a season, prepend it so last ep is an ep, not a season
	# 					if ($se =~ m!^s!){ $dbh->{$lc_title}{'ep'} = $se.'|'.$dbh->{$lc_title}{'ep'}; }
	# 					# otherwise append the ep
	# 					else { 
	# 						$dbh->{$lc_title}{'ep'} .= '|'.$se; 
	# 						$dbh->{$lc_title}{'id'} = $id;
	# 						$dbh->{$lc_title}{'le'} = $se;
	# 					}
	# 				}
	# 				# existing hash w/ no ep - when would this happen?
	# 				else { 
	# 					$dbh->{$lc_title}{'ep'} = $se;
	# 					$dbh->{$lc_title}{'id'} = $id;
	# 					$dbh->{$lc_title}{'le'} = $se;
	# 				}
	# 			}
	# 			# new hash
	# 			else {
	# 				$dbh->{$lc_title} = {
	# 					title	=> $lc_title,
	# 					type	=> $type,
	# 					ep	=> $se,
	# 					yr	=> '',
	# 					id	=> $id,
	# 					le	=> $se,
	# 				}
	# 			}
	# 		}
			
			# NoEpShows or Year .+ title  note: NO ' - ' separation, a single space followed by text is required after year. Can't match movie or ep.
			elsif (m!^([^\t]+ 19[3-9]\d|20[01]\d) ([^\t]+)\t([^\t]+\*?)?\t! or ($VAR{'NoEpShows'} and m!^($VAR{'NoEpShows'}) ([^\t]+)\t([^\t]+\*?)?\t!)){
				my $lc_title = lc($1);
				my $id = '';
				if ($3){ $id = $3; }
				if ($dbh->{$lc_title} and $dbh->{$lc_title}{'type'} eq 'LE' ){ # sub Label as Ep
					if ($id){ $dbh->{$lc_title}{$2} = $id; }
					else { $dbh->{$lc_title}{$2} = 1; }
				}
				else {
					if ($id){ $dbh->{$lc_title}{$2} = $id; }
					else { $dbh->{$lc_title}{$2} = 1; }
					$dbh->{$lc_title}{'title'} = $1; # actual db title (not lc)
					$dbh->{$lc_title}{'type'} = 'LE';
				}
			}

	# 		# NoEpShows - sub_label as ep - title - sub_label
	# 		elsif ($VAR{'NoEpShows'} and m!^($VAR{'NoEpShows'}) ([^\t]+)\t([^\t]*)\t!){
	# 			my $id = '';
	# 			if ($3){ $id = $3; }
	# 			if ($dbh->{$1} and $dbh->{$1}{'type'} eq 'LE' ){ # sub Label as Ep
	# 				if ($id){ $dbh->{$1}{$2} = $id; }
	# 				else { $dbh->{$1}{$2} = 1; }
	# 			}
	# 			else {
	# 				if ($id){ $dbh->{$1}{$2} = $id; }
	# 				else { $dbh->{$1}{$2} = 1; }
	# 				$dbh->{$1}{'title'} = $1;
	# 				$dbh->{$1}{'type'} = 'LE';
	# 			}
	# 		}

			# No year or episode (or a duplicate record)
			elsif (m!^([^\t]+)\t([^\t]+\*?)?\t!){
				my $lc_title = lc($1);
				my $id = '';
				if ($dbh->{$lc_title}){
					next; # already have an entry, skip this one to prevent collisions
				}
				else { # no ep label, use noep marker instead (=> $id if we have one)
					if ($2){ $dbh->{$lc_title}{'noep'} = $2; }
					else { $dbh->{$lc_title}{'noep'} = 1; }
					$dbh->{$lc_title}{'title'} = $1; # actual db title (not lc)
					$dbh->{$lc_title}{'type'} = 'OT';
				}
			}
		}
		close RDB or warn $!;
	}
	return $dbh;
}

sub Get_Links { 
	my ($site, $cat_name, $an, $sh, $tt, $user_agent, $free, $new_nzbs, $type, $max_nzbs, $dst_cat, $message) = @_;
	#my $type = '';
	my $spaces = '&nbsp;&nbsp;&nbsp;';
	my $watch = 1;
	my $fetch = 0;
	my $new_ep = '';
	my $save_title = $sh->{$an}{'title'}; # ends up title ep/yr
	my $lc_title = lc($sh->{$an}{'title'});
	# sh title > save title - could cause trouble - basically a shortcut, $sh->{$an}{'title'} VS $wh->{$sh->{$an}{'title'}}{'save_title'}
	if ($wh->{$lc_title}{'title'}){ 
		$save_title = $wh->{$lc_title}{'save_title'}; 
		$lc_title = lc($save_title); # need it to be save title
	}
	#if ($wh->{$sh->{$an}{'title'}}{'title'}){ $sh->{$an}{'title'} = $wh->{$sh->{$an}{'title'}}{'save_title'}; }
	# encoded save title
	my $enc_nt = $save_title;
	$enc_nt =~ s!([\W])!"%" . uc(sprintf("%2.2x",ord($1)))!eg;
	# encoded label 
	my $s_la = '';
	#my $nnn = ''; 
	if ($sh->{$an}{'label'}){ 
		#if ($sh->{$an}{'s'} and $sh->{$an}{'e'}){
		#	$nnn = $sh->{$an}{'s'}.$sh->{$an}{'e'};
		#}
		$s_la = ' '.$sh->{$an}{'label'}; 
		$s_la =~ s!([\W])!"%" . uc(sprintf("%2.2x",ord($1)))!eg;
	}
	# encoded sub label, typ ep title - just in case
	my $enc_sl = '';
	if ($VAR{'EpTitle'} and $sh->{$an}{'sub_label'}){ 
		$enc_sl = ' - '.$sh->{$an}{'sub_label'};
		$enc_sl =~ s!([\W])!"%" . uc(sprintf("%2.2x",ord($1)))!eg;
	}
	# moved to TV, only use so far
# 	unless ($sh->{$an}{'res'}){
# 		$sh->{$an}{'res'} = $XX_res{$cat_name};
# 	}
	
	# ### Movies ### first should allow for alternate $dst_cat's
	#if (($type and $type eq 'Vid') or $cat_name =~ m!^(?:search_)?Movies! or ($dst_cat and $dst_cat eq $VAR{'VidNzbs'})){#$cat_name eq 'My-Movies'){
	if ($type and $type eq 'Vid'){
# 		unless ($type){ 
# 			$type = 'Vid'; 
# 			&Print ('  Did not have $type for: '.$cat_name.' (NNC3)', 4, 0);
# 		}
		unless ($dst_cat){ 
			$dst_cat = $VAR{'VidNzbs'}; 
			#&Print ('  Did not have $dst_cat for: '.$cat_name.' (NNC3)', 4, 0);
		}
		# ### LINKS
		if ($tt){
			# + link after IMDb link
			$sh->{$an}{'links'} .= "&nbsp;<a href=\"$VAR{'DbCgi'}?do=sr&amp;tt=tt$tt&amp;nt=$enc_nt&amp;yr=$sh->{$an}{'label'}&amp;db=sr&amp;re=$site\_$cat_name:$an\"><b>+</b></a>";
			# TMDb link after nzb site link
			$sh->{$an}{'links'} .= "$spaces<a href=\"$VAR{'DbCgi'}?do=tmdb&amp;tt=tt$tt&amp;nt=$enc_nt$s_la&amp;id=&amp;db=&amp;re=$site\_$cat_name:$an\">TMDb</a>";
			# OMDb
			$sh->{$an}{'links'} .= "$spaces<a href=\"$VAR{'DbCgi'}?do=limdb&amp;tt=tt$tt&amp;nt=$enc_nt$s_la&amp;db=&amp;re=$site\_$cat_name:$an\">OMDb</a>";
			# IAO
			$sh->{$an}{'links'} .= "$spaces<a href=\"$VAR{'DbCgi'}?do=apiorg&amp;tt=tt$tt&amp;nt=$enc_nt$s_la&amp;db=&amp;re=$site\_$cat_name:$an\">IAO</a>";
		}
		else { 
			# TMDb link after nzb site link
			$sh->{$an}{'links'} .= "$spaces<a href=\"$VAR{'DbCgi'}?do=tmdb&amp;tt=&amp;nt=$enc_nt$s_la&amp;id=&amp;db=&amp;re=$site\_$cat_name:$an\">TMDb</a>";
			# OMDb
			$sh->{$an}{'links'} .= "$spaces<a href=\"$VAR{'DbCgi'}?do=limdb&amp;tt=&amp;nt=$enc_nt$s_la&amp;db=&amp;re=$site\_$cat_name:$an\">OMDb</a>";
			# IAO
			$sh->{$an}{'links'} .= "$spaces<a href=\"$VAR{'DbCgi'}?do=apiorg&amp;tt=&amp;nt=$enc_nt$s_la&amp;db=&amp;re=$site\_$cat_name:$an\">IAO</a>";
		}
		# subs link for all listings
		$sh->{$an}{'links'} .= $spaces.'Subs: <A HREF="http://subscene.com/filmsearch.aspx?q='.$enc_nt.'">SC</A>';
		# $tt subs links
		if ($tt){
			$sh->{$an}{'links'} .= "&nbsp;<A HREF=\"http://www.opensubtitles.com/en/search/sublanguageid-eng/imdbid-$tt\">OS</A>";
			#$sh->{$an}{'links'} .= "&nbsp;<A HREF=\"http://www.subtitlesource.org/title/tt$tt/\">SS</A>&nbsp;<A HREF=\"http://www.opensubtitles.com/en/search/sublanguageid-eng/imdbid-$tt\">OS</A>";
			$tt = '';
		}
		$sh->{$an}{'links'} .= '<br>';

		# ### DB (YR|OT) only
		if ($dbh->{$lc_title}{'title'}){# and $dbh->{$sh->{$an}{'title'}}{'type'} !~ m!^(?:SE|DE|LE)!){
			my $db_id = '';
			my $p_year;
			my $n_year;
			if ($sh->{$an}{'label'} =~ m!\d{4}!){
				$p_year = $sh->{$an}{'label'} - 1;
				$n_year = $sh->{$an}{'label'} + 1;
			}
			
			# year match           title                 year (= status/id)
			if ($sh->{$an}{'label'} and $dbh->{$lc_title}{$sh->{$an}{'label'}}){
				if ($dbh->{$lc_title}{$sh->{$an}{'label'}} ne '1'){ $db_id = ' ('.$dbh->{$lc_title}{$sh->{$an}{'label'}}.')'; }
				$sh->{$an}{'db_data'} .= "<br><B class=\"DEBUG\">Db has:</B> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt&re=$site\_$cat_name:$an\">$save_title</A> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$sh->{$an}{'label'}&re=$site\_$cat_name:$an\">$sh->{$an}{'label'}</A>$db_id";
				$sh->{$an}{'class'} = 'DEBUG';
				$watch = 10;
				$watch = &hold_tests ($save_title, $sh->{$an}{'label'}, $dbh->{$lc_title}{$sh->{$an}{'label'}});
# 				# check to see if database year id = VidHold
# 				if ($dbh->{$lc_title}{$sh->{$an}{'label'}} eq 'VidHold'){ # year = id/VidHold
# 					$watch = 9; # have nzb on hold, may want this one, check TvHoldLabels later
# 					&Print ('  Db has TvHold match for '.$save_title.' '.$sh->{$an}{'label'}.' (GLT1)', 5, 0);
# 				}
# 				# check to see if database year id = <status>* - status could be queued, got, etc.
# 				elsif ($dbh->{$lc_title}{$sh->{$an}{'label'}} =~ m!\*$!){
# 					&Print ('  Db has got fix flag for '.$save_title.' '.$sh->{$an}{'label'}.' (GLT1)', 5, 0);
# 					$watch = 13; # already have/had get fix nzb
# 				}
			}
			# previous yer
			elsif ($p_year and $dbh->{$lc_title}{$p_year}){
				if ($dbh->{$lc_title}{$p_year} ne '1'){ $db_id = ' ('.$dbh->{$lc_title}{$p_year}.')'; }
				$sh->{$an}{'db_data'} .= "<br><B class=\"DEBUG\">Db has:</B> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt&re=$site\_$cat_name:$an\">$save_title</A> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$p_year&re=$site\_$cat_name:$an\">$p_year</A>$db_id";
				$sh->{$an}{'class'} = 'DEBUG';
				$watch = 10;
				$watch = &hold_tests ($save_title, $p_year, $dbh->{$lc_title}{$p_year});
			}
			# next year
			elsif ($n_year and $dbh->{$lc_title}{$n_year}){
				if ($dbh->{$lc_title}{$n_year} ne '1'){ $db_id = ' ('.$dbh->{$lc_title}{$n_year}.')'; }
				$sh->{$an}{'db_data'} .= "<br><B class=\"DEBUG\">Db has:</B> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt&re=$site\_$cat_name:$an\">$save_title</A> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$n_year&re=$site\_$cat_name:$an\">$n_year</A>$db_id";
				$sh->{$an}{'class'} = 'DEBUG';
				$watch = 10;
				$watch = &hold_tests ($save_title, $n_year, $dbh->{$lc_title}{$n_year});
			}
			else {
				# there is no 'label', only an actual year key w/ id value
				#if ($dbh->{$lc_title}{'label'} and $dbh->{$lc_title}{'label'} ne '1'){ $db_id = $dbh->{$lc_title}{'label'}; }
				$sh->{$an}{'db_data'} .= "<br><B class=\"DEBUG\">Db has:</B> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt&re=$site\_$cat_name:$an\">$save_title</A>";
				#$watch = 10; # commented in r157 so it goes through watchlist checks
			}
		}
		else {
			$sh->{$an}{'db_data'} = '<br>Db search: ';
			my @keywords = split(/ /, $save_title);
			foreach (@keywords){
				unless (m!^(?:.{1,2}|a[nl][dl]|off|top|the|h[ei][rs]|not| )$!i){
				#unless (m!^(?:a(?:t|nd?|ll)?|in?|o[nf]+|t(?:op?|h(?:e|is))|not?|vs?|-|\d|\w| )$!i){
					$sh->{$an}{'db_data'} .= "<A HREF=\"$VAR{'DbCgi'}?do=search_db&amp;kw=$_&amp;re=$site\_$cat_name:$an\">$_</A>, ";
				}
			}	
			$sh->{$an}{'db_data'} =~ s!, $!!;	
			$sh->{$an}{'db_data'} .= "&nbsp;&nbsp;&nbsp;<a href=\"$VAR{'DbCgi'}?do=Add_db_form&amp;nt=$enc_nt$s_la&amp;ot=&amp;id=&amp;db=&amp;de=&amp;re=$site\_$cat_name:$an\">Db add</a>";
			$sh->{$an}{'db_data'} .= "&nbsp;(<a href=\"$VAR{'DbCgi'}?do=Add_db_form&amp;nt=$enc_nt$s_la&amp;ot=&amp;id=seen&amp;db=&amp;de=&amp;re=$site\_$cat_name:$an\">seen</a>";
			$sh->{$an}{'db_data'} .= "&nbsp;<a href=\"$VAR{'DbCgi'}?do=Add_db_form&amp;nt=$enc_nt$s_la&amp;ot=&amp;id=ignore&amp;db=&amp;de=&amp;re=$site\_$cat_name:$an\">ignore</a>)";
		}

		# ### QUEUE
		my $q_cat = $VAR{'VidNzbs'};
		$q_cat =~ s!/Sample$!!;
		# queue links
		if ($q_cat eq 'HoldDir'){ # Since Vid = HoldDir we have no way to sample or queue to a Vid dir, so list all possible cats
			# same as in TV and copied from if elsif ($VAR{'Categories'}){ ( - further down, after TV block and dst block
			#$sh->{$an}{'links'} .= $spaces; # this line is used in elsif, not wanted/needed here
			$sh->{$an}{'queue'} = '<br>Queue to: ';# TODO sub 3x use of if holddir
			my @Categories = split (m!\|!, $VAR{'Categories'});
			foreach (@Categories){ 
				$sh->{$an}{'queue'} .= "<a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=$_&amp;sc=$site\_$cat_name:$an\">$_</a> ";
			}
			if ($VAR{'HoldDir'}){# and $dst_cat !~ m!hold$!){
				$sh->{$an}{'queue'} .= " <a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=hold&amp;sc=$site\_$cat_name:$an\">hold</a>";
			}
		}
		else {
			$sh->{$an}{'queue'} = "<br><a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=$q_cat&amp;sc=$site\_$cat_name:$an\">Queue</a> ";
			my $q_paren;
			if (-e "$VAR{'NzbDir'}/$q_cat/Sample"){
				$q_paren = "<a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=$q_cat/Sample&amp;sc=$site\_$cat_name:$an\">sample</a> ";
			}
			if ($VAR{'HoldDir'} and $VAR{'VidNzbs'} !~ m!hold$! and $VAR{'VidNzbs'} !~ m!HoldDir$!){
				$q_paren .= "<a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=hold&amp;sc=$site\_$cat_name:$an\">hold</a>";
			}
			if ($q_paren){ $sh->{$an}{'queue'} .= '('.$q_paren.')'; }
		}
		
		# edit title link
		$sh->{$an}{'queue'} .= "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_title_form&amp;nt=$enc_nt$s_la&amp;ot=$sh->{$an}{'orig_title'}&amp;sc=$site\_$cat_name:$an\">Edit title</a>";

		# My Movies/Cart
		if (($VAR{'NN_Watch'} and $cat_name eq 'Movies' and $Sites{$site}{'Movies'} eq '-4') or ($VAR{'NN_Cart'} and $cat_name eq 'My-Cart')){
			# there is only one $wh check before we get here (wh save_title > sh title)
			# if this doesn't match, have hold (9) is passed on as if it were new - watch 1 and 9 > queue if they pass all checks
			if ($VAR{'VidHoldLabels'} and $sh->{$an}{'tail'} =~ m!($VAR{'VidHoldLabels'})!i){
				if ($watch == 9){ $watch = 10; } # set to got
				elsif ($watch == 1){ $watch = 2; } # no db entry (10), send it to hold
			}
			# nzb in db (hold or std), but not a get fix match (13), run it through checks if we have a match
			elsif ($watch == 10 and $VAR{'GetFix'} and $sh->{$an}{'tail'} =~ m!($VAR{'GetFix'})!i){
				# movies have a lot more releases and there's no way to no if the fix applies
				# but it shouldn't be on watchlist if we're happy w/ what we have
				# and it would be downloaded anyway, better to send it to hold
				$watch = 3;
			}
			# so we don't try to update watchlist - hold = 2, fix = 3, cart/my-shows = 4
			# while watch list update would be a nice touch in some cases, we cannot count on it - keep this independent of watch list
			else { $watch = 4; }
			
			if  ($watch < 10){
				#$save_title = $sh->{$an}{'title'};
				if ($VAR{'Year'} and $sh->{$an}{'label'}){
					$save_title .= ' '.$sh->{$an}{'label'};
				}
				#$fetch = 1;
				#$fetch = &nzb_tests ($save_title, $sh->{$an}{'size'}, $sh->{$an}{'age'}, $sh->{$an}{'tail'}, $max_nzbs, $sh->{$an}{'group'}, $sh->{$an}{'poster'}, $sh->{$an}{'complete'});
				$fetch = &nzb_tests ($save_title, $max_nzbs, $an, $sh);
				# all these moved to nzb_tests
# 				if ($fetch and  $sh->{$an}{'complete'} and $sh->{$an}{'complete'}< 100){
# 					$fetch = 0;
# 					&Print ('  '.$save_title.' is only '. $sh->{$an}{'complete'}.'percent complete, skipping (GLI0)', 3, 0);
# 				}
# 				# skip group all these moved to nzb_tests
# 				elsif ($fetch and  $VAR{'SkipGroup'} and $VAR{'SkipGroup'}=~ m!\b(\Q$sh->{$an}{'group'}\E)\b!i){
# 					$fetch = 0;
# 					&Print ('  '.$save_title.' has a '.$1.' SkipGroup match, skipping (GLSG)', 3, 0);
# 				}
			}
		}
		# watch link/status 
		#if ($watch and $wh->{$lc_title}{'yr'}){
		elsif ($wh->{$lc_title}{'yr'}){
			my $w_year = $wh->{$lc_title}{'yr'};
			my $l_year = $sh->{$an}{'label'};
			# ### FETCH  - see if we want it 
			
			# if this doesn't match, have hold (9) is passed on as if it were new - watch 1 and 9 get queued if they pass all checks
			if ($VAR{'VidHoldLabels'} and $sh->{$an}{'tail'} =~ m!($VAR{'VidHoldLabels'})!i){
				if ($watch == 9){ $watch = 10; } # have hold, we don't want another, set to got
				elsif ($watch == 1){ $watch = 2; } # no db entry (10), send it to hold
			}
			# queued nzb in db, but not a get fix match (13), run it through checks
			elsif ($watch == 10 and $VAR{'GetFix'} and $sh->{$an}{'tail'} =~ m!($VAR{'GetFix'})!i){
				# movies have a lot more releases and there's no way to no if the fix applies
				&Print ('  FYI only, '.$save_title.' '.$l_year.' has a $1 GetFix match (GLM1)', 3, 0);
				#$watch = 3; # > hold
			}
			
			# check res - must match - watch = listing
			if ($watch < 10 and $l_year and ($l_year == $w_year or $l_year == ($w_year - 1) or $l_year == ($w_year + 1))){
				$fetch = 1; # <<<<<<<<<<< if no matches it becomes 0 again
				my $found = 0;
				$save_title = $wh->{$lc_title}{'save_title'}.' '.$w_year;
				# anything
				if ($wh->{$lc_title}{'res'} eq 'AL'){
					&Print ('  '.$save_title.' '.$l_year.' has AL match - no minimum quality restriction (GLM1)', 4, 0);
					$new_ep = $w_year;
				}
# 				elsif ($sh->{$an}{'tail'} =~ m!($Vid_Qual{'CM'})!i){
# 					unless ($wh->{$lc_title}{'res'} eq 'CM'){ $found = 1; $fetch = 0; }
# 				}
# 				elsif ($sh->{$an}{'tail'} =~ m!($Vid_Qual{'TS'})!i){
# 					unless ($wh->{$lc_title}{'res'} eq 'TS'){ $found = 1; $fetch = 0; }
# # 					if ($wh->{$lc_title}{'res'} eq 'TS' and !$found){
# # 					}
# # 					else { $found = 1; }
# 				}
# 				elsif ($sh->{$an}{'tail'} =~ m!($Vid_Qual{'SC'})!i){
# 					if ($wh->{$lc_title}{'res'} eq 'SC' and !$found){
# 					}
# 					else { $found = 1; }
# 				}
# 				elsif ($sh->{$an}{'tail'} =~ m!($Vid_Qual{'VD'})!i){
# 					if ($wh->{$lc_title}{'res'} eq 'VD' and !$found){
# 					}
# 					else { $found = 1; }
# 				}
# 				elsif ($sh->{$an}{'tail'} =~ m!($Vid_Qual{'R5'})!i){
# 					if ($wh->{$lc_title}{'res'} eq 'R5' and !$found){
# 					}
# 					else { $found = 1; }
# 				}
# 				elsif ($sh->{$an}{'tail'} =~ m!($Vid_Qual{'DR'})!i){
# 					if ($wh->{$lc_title}{'res'} eq 'DR' and !$found){
# 						if ($sh->{$an}{'tail'} !~ m!xvid!i){
# 							&Print ('  '.$save_title.' '.$l_year.' does not have XviD match, skipping (GLM1)', 4, 0);
# 							$fetch = 0;
# 						}
# 					}
# 					else { $found = 1; }
# 				}
# 				# 	R5 => 'R[C2456]',
# 				# 	VD => '[VWP][OEP][DBV][ -]?Rip',
# 				# 	SC => 'DVD[. -]?SCR|SCR(?:EENER|[ -]?RIP)?',
# 				# 	TS => 'TC|TELECINE|TS|TELESYNC|(?:HD)?CAM',
				
				# listing tail has (foo|bar|baz) match, quality level BD, DD, HD, SD,
				elsif ($sh->{$an}{'tail'} =~ m!($Vid_Qual{$wh->{$lc_title}{'res'}})!i){
					my $match = $1;
					&Print ('  '.$save_title.' '.$l_year.' has '.$wh->{$lc_title}{'res'}.' '.$match.' match (GLM1)', 4, 0);
					$new_ep = $w_year;
					# 720p or 1080p match
					if ($VAR{'HdRes'} and $sh->{$an}{'tail'} !~ m!$VAR{'HdRes'}!){
						&Print ('  '.$save_title.' '.$l_year.' does not have '.$VAR{'HdRes'}.' match, skipping (GLM1)', 4, 0);
						$fetch = 0;
					}
					# BD and DD Remux Remastered Untouched COMPLETE CUSTOM - WMV AVC(HD) - BD(DK) - DUAL MULTi
					elsif ($wh->{$lc_title}{'res'} eq 'BD' or $wh->{$lc_title}{'res'} eq 'DD'){
						# cannot match xvid or x264
						if ($sh->{$an}{'tail'} =~ m!(xvid)!i or $sh->{$an}{'tail'} =~ m!([xh]264)!i){
							&Print ('  '.$save_title.' '.$l_year.' has '.$1.' match, skipping (GLM1)', 4, 0);
							$fetch = 0;
						}
						# BD must be greater than 10GB
						elsif ($wh->{$lc_title}{'res'} eq 'BD' and $sh->{$an}{'size'} < 10240){
							&Print ('  '.$save_title.' '.$l_year.' is smaller than 10GB, skipping (GLM1)', 4, 0);
							$fetch = 0;
						}
# 						# BD BluRay must have another label match
# 						elsif ($wh->{$lc_title}{'res'} eq 'BD' and $match eq 'BluRay'){
# 							unless ($sh->{$an}{'tail'} =~ m!(complete|remux|untouched|custom|WMV|AVC(?:HD)?)!i){
# 								&Print ('  '.$save_title.' '.$l_year.' has no BluRay type matches, skipping (GLM1)', 4, 0);
# 								$fetch = 0;
# 							}
# 						}
						# DD must be greater than 3GB
						elsif ($wh->{$lc_title}{'res'} eq 'DD' and $sh->{$an}{'size'} < 3072){
							&Print ('  '.$save_title.' '.$l_year.' is smaller than 3GB, skipping (GLM1)', 4, 0);
							$fetch = 0;
						}
# 						#&Print ('  '.$save_title.' '.$l_year.' has '.$1.' match, skipping (GLM1)', 4, 0);
# 						$fetch = 0;
					}
					# HD must have x264 match
					elsif ($wh->{$lc_title}{'res'} eq 'HD' and $sh->{$an}{'tail'} !~ m!([xh]264)!i){
						&Print ('  '.$save_title.' '.$l_year.' does not have x264 match, skipping (GLM1)', 4, 0);
						$fetch = 0;
					}
					# DR (SD) must have xvid match
# 					elsif ($wh->{$lc_title}{'res'} eq 'DR' and $sh->{$an}{'tail'} !~ m!xvid!i){
# 							&Print ('  '.$save_title.' '.$l_year.' does not have XviD match, skipping (GLM1)', 4, 0);
# 							$fetch = 0;
# 					}
				}
				else {
					#&Print ('  '.$save_title.' '.$l_year.' does not have a '.$wh->{$lc_title}{'res'}.' match, skipping (GL01)', 4, 0); 
					$fetch = 0;
				}
			}
			# apply other tests, could become 0 again
			if ($fetch){
				$fetch = &nzb_tests ($save_title, $max_nzbs, $an, $sh);
# 				if ($fetch and  $sh->{$an}{'complete'} and $sh->{$an}{'complete'}< 100){
# 					$fetch = 0;
# 					&Print ('  '.$save_title.' is only '. $sh->{$an}{'complete'}.'percent complete, skipping (GLI0)', 3, 0);
# 				}
# 				# skip group
# 				elsif ($fetch and  $VAR{'SkipGroup'} and $VAR{'SkipGroup'}=~ m!\b(\Q$sh->{$an}{'group'}\E)\b!i){
# 					$fetch = 0;
# 					&Print ('  '.$save_title.' has a '.$1.' SkipGroup match, skipping (GLSG)', 3, 0);
# 				}
			}
			$sh->{$an}{'queue'} .= $spaces.'<B class="DEBUG">On Watch List ('.$wh->{$lc_title}{'res'}.')</B>'; # $sh->{$an}{'queue'} .= $spaces.'<B class=\"DEBUG\"><a href="'.$VAR{'WfCgi'}.'?watchlist#VIDEO">On Watch List</a></B>';
		}
		elsif ($sh->{$an}{'label'}){ # year label
			$sh->{$an}{'queue'} .= "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_watch_form&amp;nt=$enc_nt&amp;la=$sh->{$an}{'label'}&amp;ca=VD&amp;sc=$site\_$cat_name:$an\">Add to Watch List</a>";
		}
		else { $sh->{$an}{'queue'} .= "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_watch_form&amp;nt=$enc_nt&amp;la=&amp;ca=VD&amp;sc=$site\_$cat_name:$an\">Add to Watch List</a>"; }
	}
	# ### TV ###
	# Get_Links vars we may need if we sub this: $type, $spaces, $watch, $fetch, $save_title, $enc_nt, $enc_sl, $s_la, $nnn ($site, $cat_name, $an, $sh, $tt, $user_agent, $dst_cat)
	#elsif (($type and $type eq 'Tv') or $cat_name =~ m!^(?:search_)?TV! or ($dst_cat and $dst_cat eq $VAR{'TvNzbs'}) or $cat_name eq 'My-Shows'){
	elsif ($type and $type eq 'Tv'){
# 		unless ($type){ 
# 			$type = 'Tv'; 
# 			&Print ('  Did not have $type for: '.$cat_name.' (NNC3)', 4, 0);
# 		}
		unless ($dst_cat){ 
			$dst_cat = $VAR{'TvNzbs'}; 
			#&Print ('  Did not have $dst_cat for: '.$cat_name.' (NNC3)', 4, 0);
		}
		unless ($sh->{$an}{'res'}){
			$sh->{$an}{'res'} = $XX_res{$cat_name};
		}
		my $nnn = '';
		my $sN = '';
		if ($sh->{$an}{'s'} and $sh->{$an}{'e'}){
			$nnn = $sh->{$an}{'s'}.$sh->{$an}{'e'};
			$sN = 's'.$sh->{$an}{'s'};
			$sN =~ s!^s(\d)$!s0$1!;
		}
		elsif ($sh->{$an}{'s'}){ # when only s is passed its a season label already
			$sN = $sh->{$an}{'s'};
		}
		my $f_label; # formated label
		
		# ### LINKS - TVDb link after nzb site link
		$sh->{$an}{'links'} .= $spaces."TVDb: <a href=\"$VAR{'DbCgi'}?do=tvdb&amp;nt=$enc_nt&amp;ep=&amp;id=&amp;db=&amp;re=$site\_$cat_name:$an\">show</a> <a href=\"$VAR{'DbCgi'}?do=tvdb&amp;nt=$enc_nt&amp;ep=$sh->{$an}{'label'}&amp;id=&amp;db=&amp;re=$site\_$cat_name:$an\">ep</a>";
		$sh->{$an}{'links'} .= '<br>';
		
		# ### DB (OT|SE|DE) db hash is: $dbh->{title}{ep/yr = id, title = title, type = YR|SE|DE|OT }
		my $db_id = ''; # TODO $status would be more consistent
		if ($dbh->{$lc_title}{'title'}){
			# nnn ep match
			if ($nnn and $dbh->{$lc_title}{$nnn}){ # and $dbh->{$lc_title}{'type'} eq 'SE'){ #  and $dbh->{$lc_title}{'type'} eq 'SE'
				#if ($dbh->{$lc_title}{$nnn} ne '1'){ $db_id = ' ('.$dbh->{$lc_title}{$nnn}.')'; }
				if ($dbh->{$lc_title}{$nnn} ne '1'){ $db_id = ' ('.$dbh->{$lc_title}{$nnn}.')'; }
				$sh->{$an}{'db_data'} .= "<br><B class=\"DEBUG\">Db has:</B> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt&re=$site\_$cat_name:$an\">$save_title</A> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt\%20$nnn&re=$site\_$cat_name:$an\">$nnn</A>$db_id";
				$sh->{$an}{'class'} = 'DEBUG';
				$watch = 10;
				$watch = &hold_tests ($save_title, $nnn, $dbh->{$lc_title}{$nnn});
# 				# check to see if database ep id = TvHold - need ep in db format for nnn, others (sN dd-dd-dd) should match listing format
# 				if ($dbh->{$lc_title}{$nnn} eq 'TvHold'){ # ep/nnn = id/TvHold
# 					$watch = 9; # < 10 = fetch 1 unless fails TvHoldLabels check later
# 					&Print ('  Db has TvHold match for '.$save_title.' '.$nnn.' (GLT1)', 5, 0);
# 				}
# 				# check to see if database ep id = <status>* - status could be queued, got, etc.
# 				elsif ($dbh->{$lc_title}{$nnn} =~ m!\*$!){
# 					&Print ('  Db has got fix flag for '.$save_title.' '.$nnn.' (GLT1)', 5, 0);
# 					$watch = 13; # already have/had get fix nzb
# 				}
			}
			# SnnDn - DVD season disks
			elsif ($sh->{$an}{'m'} =~ m!^(\d)$! and $dbh->{$lc_title}{$sN.'d'.$1}){
				my $sd = $sN.'d'.$1;
				if ($dbh->{$lc_title}{$sd} ne '1'){ $db_id = ' ('.$dbh->{$lc_title}{$sd}.')'; }
				$sh->{$an}{'db_data'} .= "<br><B class=\"DEBUG\">Db has:</B> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt&re=$site\_$cat_name:$an\">$save_title</A> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt\%20$sd&re=$site\_$cat_name:$an\">$sd</A>$db_id";
				$sh->{$an}{'class'} = 'DEBUG';
				$watch = 10;
				$watch = &hold_tests ($save_title, $sd, $dbh->{$lc_title}{$sd});
			}
			# $nnn listing matches db sN ($nnn translated to $sN) - ep season matches db title sN
			elsif ($sN and $dbh->{$lc_title}{$sN}){ # and $dbh->{$lc_title}{'type'} eq 'SE'){
				if ($dbh->{$lc_title}{$sN} ne '1'){ $db_id = ' ('.$dbh->{$lc_title}{$sN}.')'; }
				$sh->{$an}{'db_data'} .= "<br><B class=\"DEBUG\">Db has:</B> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt&re=$site\_$cat_name:$an\">$save_title</A> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt\%20$sN&re=$site\_$cat_name:$an\">$sN</A>$db_id";
				$sh->{$an}{'class'} = 'DEBUG';
				$watch = 10;
				# not a current ep, no need to check fix or hold... but we're checking all db matches anyway (e.g. next line, was on $nnn match only)
				$watch = &hold_tests ($save_title, $sN, $dbh->{$lc_title}{$sN});
			}
			# label match - sN = sN, dd-dd-dd = dd-dd-dd, etc.
			elsif ($sh->{$an}{'label'} and $dbh->{$lc_title}{$sh->{$an}{'label'}}){ # and $dbh->{$lc_title}{'type'} eq 'SE'}){
				if ($dbh->{$lc_title}{$sh->{$an}{'label'}} ne '1'){ $db_id = ' ('.$dbh->{$lc_title}{$sh->{$an}{'label'}}.')'; }
				$sh->{$an}{'db_data'} .= "<br><B class=\"DEBUG\">Db has:</B> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt&re=$site\_$cat_name:$an\">$save_title</A> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt$s_la&re=$site\_$cat_name:$an\">$sh->{$an}{'label'}</A>$db_id";
				$sh->{$an}{'class'} = 'DEBUG';
				$watch = 10;
				$watch = &hold_tests ($save_title, $sh->{$an}{'label'}, $dbh->{$lc_title}{$sh->{$an}{'label'}});
			}
			# none - no ep or sub_label, but title matches
# 			elsif ($dbh->{$lc_title}{'title'}){
# 			#elsif (!$sh->{$an}{'label'} and !$sh->{$an}{'sub_label'}){
# 				if ($dbh->{$lc_title}{'noep'} ne '1'){ $db_id = ' ('.$dbh->{$lc_title}{'noep'}.')'; }
# 				$sh->{$an}{'db_data'} .= "<br><B class=\"DEBUG\">Db has:</B> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt&re=$site\_$cat_name:$an\">$save_title</A>$db_id";
# 				$sh->{$an}{'class'} = 'DEBUG';
# 				&Print ('  Db has '.$save_title.' has no label or sub_label, use "none" to watch (GLT1)', 5, 0);
# 				$watch = 10;
# 				# needs testing - may want label_check, but seems unlikely
# 			}
			# no match, print db has w/ title search... could try $nnn - 1 test to get a has title last ep (id)
			else {
				if ($wh->{$lc_title}{'save_title'}){
					&Print ('  Db has '.$save_title.', but not '.$sh->{$an}{'label'}.' (nnn='.$nnn.', sN='.$sN.', s='.$sh->{$an}{'s'}.', e='.$sh->{$an}{'e'}.' (GLTV1)', 5, 0);
				}
				$sh->{$an}{'db_data'} .= "<br><B class=\"DEBUG\">Db has:</B> <A HREF=\"$VAR{'DbCgi'}?do=search_db&kw=$enc_nt&re=$site\_$cat_name:$an\">$save_title</A>";
				$sh->{$an}{'db_data'} .= "&nbsp;&nbsp;&nbsp;<a href=\"$VAR{'DbCgi'}?do=Add_db_form&amp;nt=$enc_nt$s_la$enc_sl&amp;ot=&amp;id=&amp;db=&amp;de=&amp;re=$site\_$cat_name:$an\">Db add</a>";
				$sh->{$an}{'db_data'} .= "&nbsp;(<a href=\"$VAR{'DbCgi'}?do=Add_db_form&amp;nt=$enc_nt$s_la$enc_sl&amp;ot=&amp;id=seen&amp;db=&amp;de=&amp;re=$site\_$cat_name:$an\">seen</a>";
				$sh->{$an}{'db_data'} .= "&nbsp;<a href=\"$VAR{'DbCgi'}?do=Add_db_form&amp;nt=$enc_nt$s_la$enc_sl&amp;ot=&amp;id=ignore&amp;db=&amp;de=&amp;re=$site\_$cat_name:$an\">ignore</a>)";
			}
		}
		else {
			$sh->{$an}{'db_data'} = '<br>Db search: ';
			my $la = $s_la;
			if ($nnn){ $la = '%20'.$nnn; } # need nnn for db
			my @keywords = split(/ /, $save_title);
			foreach (@keywords){
				unless (m!^(?:.{1,2}|a[nl][dl]|off|top|the|h[ei][rs]|not| )$!i){
					$sh->{$an}{'db_data'} .= "<A HREF=\"$VAR{'DbCgi'}?do=search_db&amp;kw=$_&amp;re=$site\_$cat_name:$an\">$_</A>, ";
				}
			}	
			$sh->{$an}{'db_data'} =~ s!, $!!;	
			$sh->{$an}{'db_data'} .= "&nbsp;&nbsp;&nbsp;<a href=\"$VAR{'DbCgi'}?do=Add_db_form&amp;nt=$enc_nt$la$enc_sl&amp;ot=&amp;id=&amp;db=&amp;de=&amp;re=$site\_$cat_name:$an\">Db add</a>";
			$sh->{$an}{'db_data'} .= "&nbsp;(<a href=\"$VAR{'DbCgi'}?do=Add_db_form&amp;nt=$enc_nt$la$enc_sl&amp;ot=&amp;id=seen&amp;db=&amp;de=&amp;re=$site\_$cat_name:$an\">seen</a>";
			$sh->{$an}{'db_data'} .= "&nbsp;<a href=\"$VAR{'DbCgi'}?do=Add_db_form&amp;nt=$enc_nt$la$enc_sl&amp;ot=&amp;id=ignore&amp;db=&amp;de=&amp;re=$site\_$cat_name:$an\">ignore</a>)";
		}
		
		# ### QUEUE
		# TODO move queue this after watch tests?
		my $q_cat = $VAR{'TvNzbs'};
		$q_cat =~ s!/Sample$!!;
		# queue links
		if ($q_cat eq 'HoldDir'){ # Since TV = HoldDir we have no way to sample or queue to a TV dir, so list all possible cats
			# copied from if elsif ($VAR{'Categories'}){ ( - further down, after TV block and dst block
			#$sh->{$an}{'links'} .= $spaces; # this line is used there, not wanted/needed here
			$sh->{$an}{'queue'} = '<br>Queue to: ';
			my @Categories = split (m!\|!, $VAR{'Categories'});
			foreach (@Categories){ 
				$sh->{$an}{'queue'} .= "<a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=$_&amp;sc=$site\_$cat_name:$an\">$_</a> ";
			}
			if ($VAR{'HoldDir'}){# and $dst_cat !~ m!hold$!){
				$sh->{$an}{'queue'} .= " <a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=hold&amp;sc=$site\_$cat_name:$an\">hold</a>";
			}
		}
		else {
			$sh->{$an}{'queue'} = "<br><a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=$q_cat&amp;sc=$site\_$cat_name:$an\">Queue</a> ";
			my $q_paren;
			if (-e "$VAR{'NzbDir'}/$q_cat/Sample"){
				$q_paren = "<a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=$q_cat/Sample&amp;sc=$site\_$cat_name:$an\">sample</a> ";
			}
			if ($VAR{'HoldDir'} and $VAR{'TvNzbs'} !~ m!hold$! and $VAR{'TvNzbs'} !~ m!HoldDir$!){
				$q_paren .= "<a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=hold&amp;sc=$site\_$cat_name:$an\">hold</a>";
			}
			if ($q_paren){ $sh->{$an}{'queue'} .= '('.$q_paren.')'; }
		}
		
		# edit title link
		$sh->{$an}{'queue'} .= "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_title_form&amp;nt=$enc_nt$s_la$enc_sl&amp;ot=$sh->{$an}{'orig_title'}&amp;sc=$site\_$cat_name:$an\">Edit title</a>";
		
		# My Shows/Cart
		if (($VAR{'NN_Watch'} and $cat_name eq 'TV' and  $Sites{$site}{'TV'} eq '-3') or ($VAR{'NN_Cart'} and $cat_name eq 'My-Cart')){
			# there is only one $wh check before we get here (wh save_title > sh title)
			# if this doesn't match, have hold (9) is passed on as if it were new - watch 1 and 9 > queue if they pass all checks
			if ($VAR{'TvHoldLabels'} and $sh->{$an}{'tail'} =~ m!($VAR{'TvHoldLabels'})!i){
				if ($watch == 9){ $watch = 10; } # set to got
				elsif ($watch == 1){ $watch = 2; } # no db entry (10), send it to hold
			}
			# nzb in db (hold or std), but not a get fix match (13), run it through checks if we have a match
			elsif ($watch == 10 and $VAR{'GetFix'} and $sh->{$an}{'tail'} =~ m!($VAR{'GetFix'})!i){
				$watch = 3;
			}
			# so we don't try to update watchlist - hold = 2, fix = 3, cart/my-shows = 4
			# while watch list update would be a nice touch in some cases, we cannot count on it - keep this independent of watch list
			else { $watch = 4; }
			
			# just format (and fetch ep title)
			if  ($watch < 10){
				if ($nnn){
					($f_label, $new_ep) = &FormatLabel ($sh->{$an}{'s'}, $sh->{$an}{'e'}, $sh->{$an}{'m'});
					#$save_title = $sh->{$an}{'title'}.' '.$f_label;
					$save_title .= ' '.$f_label;
					if ($VAR{'EpTitle'} and ($sh->{$an}{'sub_label'} or ($sh->{$an}{'sub_label'} = &GetEpTitle ($save_title, $sh->{$an}{'s'}, $sh->{$an}{'e'}, $user_agent, '')))){
						$save_title .= ' - '.$sh->{$an}{'sub_label'};
					}
					#$new_ep = $nnn;
				}
				elsif ($sh->{$an}{'label'} =~ m!(\d{2}-\d{2}-\d{2})!){
					my $label = $1;
					#$save_title = $sh->{$an}{'title'}.' '.$label;
					$save_title .= ' '.$label;
					if ($VAR{'EpTitle'} and ($sh->{$an}{'sub_label'} or ($sh->{$an}{'sub_label'} = &GetEpTitle ($save_title, '', $label, $user_agent, '')))){
						$save_title .= ' - '.$sh->{$an}{'sub_label'};
					}
					$new_ep = $label;
				}
				elsif ($sh->{$an}{'label'}){
					#$save_title = $sh->{$an}{'title'}.' '.$sh->{$an}{'label'};
					$save_title .= ' '.$sh->{$an}{'label'};
					if ($sh->{$an}{'sub_label'}){ $save_title .= ' - '.$sh->{$an}{'sub_label'}; }
					$new_ep = $sh->{$an}{'label'};
				}
				else { 
					#$save_title = $sh->{$an}{'title'}; 
					if ($sh->{$an}{'sub_label'}){ $save_title .= ' - '.$sh->{$an}{'sub_label'}; }
					$new_ep = 'none';
				}
				#$fetch = 1;
				$fetch = &nzb_tests ($save_title, $max_nzbs, $an, $sh);
# 				if ($fetch and  $sh->{$an}{'complete'} and $sh->{$an}{'complete'}< 100){
# 					$fetch = 0;
# 					&Print ('  '.$save_title.' is only '. $sh->{$an}{'complete'}.'percent complete, skipping (GLI0)', 3, 0);
# 				}
# 				# skip group
# 				elsif ($fetch and  $VAR{'SkipGroup'} and $VAR{'SkipGroup'}=~ m!\b(\Q$sh->{$an}{'group'}\E)\b!i){
# 					$fetch = 0;
# 					&Print ('  '.$save_title.' has a '.$1.' SkipGroup match, skipping (GLSG)', 3, 0);
# 				}
			}
			#$sh->{$an}{'queue'} .= $spaces.'<B class="DEBUG">On Watch List ('.$wh->{$lc_title}{'res'}.')</B>'; #$sh->{$an}{'queue'} .= $spaces.'<B class=\"DEBUG\"><a href="'.$VAR{'WfCgi'}.'?watchlist#TV">On Watch List</a></B>';
		}
		
		# all TV/VID listings have $watch = 1 or 10 (10=db has) or 13 (13=db has fix)
		elsif ($wh->{$lc_title}{'ep'}){ # ep can be noep and none
			# ### FETCH - see if we want it 
			
			# if db has TvHold, we don't want another, otherwise run it through checks
			if ($VAR{'TvHoldLabels'} and $sh->{$an}{'tail'} =~ m!($VAR{'TvHoldLabels'})!i){
				if ($watch == 9){ $watch = 10; } # set to got
				elsif ($watch == 1){ $watch = 2; } # no db entry ($watch != 10), send it to hold
			}
			# nzb in db (hold or std), but not a get fix match (13), run it through checks if we have a match
			elsif ($watch == 10 and $VAR{'GetFix'} and $sh->{$an}{'tail'} =~ m!($VAR{'GetFix'})!i){
				$watch = 3;
			}
			
			# check res - must match - watch = listing
			if  ($watch < 10){ # 1/new, 2/hold, 3/fix-hold or 9/replace hold(like 1/new, fetch = 1/queued)
				$fetch = 1; # <<<<<<<<<<< if no matches it becomes 0 again
				# AT = all cats, ANY listing. HS = all cats, NEWER listing (has to pass $watch == 1 below, AT gets exception below)
				if ($wh->{$lc_title}{'res'} eq 'AT' or $wh->{$lc_title}{'res'} eq 'HS'){
					&Print ('  '.$save_title.' has '.$wh->{$lc_title}{'res'}.' match (GL01)', 4, 0);
				}
				# DD = DVDr
				elsif ($wh->{$lc_title}{'res'} eq 'DD' and $sh->{$an}{'tail'} =~ m!($Vid_Qual{'DD'})!i){
					&Print ('  '.$save_title.'  has '.$1.' match (GL01)', 4, 0);
					if ($sh->{$an}{'tail'} =~ m!(xvid)!i or $sh->{$an}{'tail'} =~ m!([xh]264)!i){
						&Print ('  '.$save_title.'  is not a disc, has '.$1.' match, skipping (GL01)', 4, 0);
						$fetch = 0;
					}
					elsif ($sh->{$an}{'size'} < 3072){
						&Print ('  '.$save_title.' is smaller than 3GB, skipping (GLM1)', 4, 0);
						$fetch = 0;
					}
				}
				# HR = High res categories
				elsif ($wh->{$lc_title}{'res'} eq 'HR' and $sh->{$an}{'res'} eq 'HR'){
					&Print ('  '.$save_title.'  has HR category match (GL01)', 4, 0);
				}
				# SR = Standard res categories
				elsif ($wh->{$lc_title}{'res'} eq 'SR' and $sh->{$an}{'res'} eq 'SR'){
					&Print ('  '.$save_title.'  has SR category match (GL01)', 4, 0);
				}
				# SA = SD XviD - dvdrips
				elsif ($wh->{$lc_title}{'res'} eq 'SA' and $sh->{$an}{'tail'} =~ m!($Vid_Qual{'SA'})!i and $sh->{$an}{'tail'} =~ m!xvid!i){
					&Print ('  '.$save_title.'  has '.$1.' match (GL01)', 4, 0);
				}
				# SX = SD x264, not > 480p $sh->{$an}{'tail'} =~ m!480p! or $sh->{$an}{'tail'} !~ m!\d+[pi]!
				elsif ($wh->{$lc_title}{'res'} eq 'SX' and $sh->{$an}{'tail'} =~ m!x264!i and ($sh->{$an}{'tail'} =~ m!480p! or $sh->{$an}{'tail'} !~ m!\d{3,4}[pix]!i)){
					&Print ('  '.$save_title.' has SD x264 match (GL01)', 4, 0);
				}
				# H7 = 720p
				elsif ($wh->{$lc_title}{'res'} eq 'H7' and $sh->{$an}{'tail'} =~ m!(720[px])!i){
					&Print ('  '.$save_title.'  has '.$1.' match (GL01)', 4, 0);
				}
				# H1 = 1080p
				elsif ($wh->{$lc_title}{'res'} eq 'H1' and $sh->{$an}{'tail'} =~ m!(1080[ipx])!i){
					&Print ('  '.$save_title.'  has '.$1.' match (GL01)', 4, 0);
				}
				else {
					&Print ('  No '.$wh->{$lc_title}{'res'}.' match found for '.$sh->{$an}{'orig_title'}.' in '.$cat_name.' (GL01)', 4, 0); 
					$fetch = 0;
				}
			}
			
			# apply other tests (before get ep title), could become 0 again
			if ($fetch){
				$fetch = &nzb_tests ($save_title, $max_nzbs, $an, $sh);
# 				if ($fetch and  $sh->{$an}{'complete'} and $sh->{$an}{'complete'}< 100){
# 					$fetch = 0;
# 					&Print ('  '.$save_title.' is only '. $sh->{$an}{'complete'}.'percent complete, skipping (GLI0)', 3, 0);
# 				}
# 				# skip group
# 				elsif ($fetch and  $VAR{'SkipGroup'} and $VAR{'SkipGroup'}=~ m!\b(\Q$sh->{$an}{'group'}\E)\b!i){
# 					$fetch = 0;
# 					&Print ('  '.$save_title.' has a '.$1.' SkipGroup match, skipping (GLSG)', 3, 0);
# 				}
			}

			# check watch list
			if  ($fetch){ # 2/TvHold, 3/GetFix, 4/'no ep match' and 5/'no ep' are db ep matches - no need to check again
				my $last_s; # last season - in case new ep is new season, for season (+ 1) match
				if ($sh->{$an}{'s'} and $sh->{$an}{'e'}){ $last_s = ($sh->{$an}{'s'} - 1); }
				
				# find ep match - nnn > nnn
				if ($nnn and $nnn > $wh->{$lc_title}{'ep'}){ # following is pointless (sN doesn't affect WL) # or ($wh->{$lc_title}{'ep'} =~ m!s0?(\d+)! and ($1 - 1) == $sh->{$an}{'s'})){
					&Print ('  '.$save_title.' '.$nnn.' > '.$wh->{$lc_title}{'ep'}.' (GL02)', 4, 0);
					($f_label, $new_ep) = &FormatLabel ($sh->{$an}{'s'}, $sh->{$an}{'e'}, $sh->{$an}{'m'});
					$save_title = $wh->{$lc_title}{'save_title'}.' '.$f_label;
					#unless ( $sh->{$an}{'sub_label'} ){
					if ($VAR{'EpTitle'} and ($sh->{$an}{'sub_label'} or ($sh->{$an}{'sub_label'} = &GetEpTitle ($wh->{$lc_title}{'save_title'}, $sh->{$an}{'s'}, $sh->{$an}{'e'}, $user_agent, $wh->{$lc_title}{'real_title'})))){
						$save_title .= ' - '.$sh->{$an}{'sub_label'};
					}
					#$new_ep = $nnn; # $sh->{$an}{'s'} >
					#$save_title .= ':'.$nnn;
				} 
				# season or season+1 match
				elsif ($nnn and $wh->{$lc_title}{'ep'} =~ m!^$sh->{$an}{'s'}! or ($last_s and $wh->{$lc_title}{'ep'} =~ m!^$last_s!)){
					&Print ('  '.$save_title.' '.$nnn.' matches the current watchlist season ('.$sh->{$an}{'s'}.') (GL02)', 4, 0);
					($f_label, $new_ep) = &FormatLabel ($sh->{$an}{'s'}, $sh->{$an}{'e'}, $sh->{$an}{'m'});
					$save_title = $wh->{$lc_title}{'save_title'}.' '.$f_label;
					if ($VAR{'EpTitle'} and ($sh->{$an}{'sub_label'} or ($sh->{$an}{'sub_label'} = &GetEpTitle ($wh->{$lc_title}{'save_title'}, $sh->{$an}{'s'}, $sh->{$an}{'e'}, $user_agent, $wh->{$lc_title}{'real_title'})))){
						$save_title .= ' - '.$sh->{$an}{'sub_label'};
					}
					#$new_ep = $nnn;
					#$save_title .= ':'.$nnn;
				}
				# date based ep
				elsif ($sh->{$an}{'label'} =~ m!(\d{2}-\d{2}-\d{2})!){
					$new_ep = $1;
					&Print ('  '.$save_title.' '.$sh->{$an}{'label'}.' is on watchlist and not in db (GL02)', 4, 0);
					$save_title = $wh->{$lc_title}{'save_title'}.' '.$sh->{$an}{'label'};
					#&Print ('  '.$save_title.' is on watchlist and not in db (GL02)', 4, 0);
					if ($VAR{'EpTitle'} and ($sh->{$an}{'sub_label'} or ($sh->{$an}{'sub_label'} = &GetEpTitle ($wh->{$lc_title}{'save_title'}, '', $new_ep, $user_agent, $wh->{$lc_title}{'real_title'})))){
						$save_title .= ' - '.$sh->{$an}{'sub_label'};
					}
				}
				# sN full season nzb match - needs watchlist removal... hard to do w/ multiple disks and it will be skipped if in db
				elsif ($sN and $wh->{$lc_title}{'ep'} eq $sN){
					&Print ('  '.$save_title.' '.$sh->{$an}{'label'}.' is on watchlist and not in db (GL02)', 4, 0);
					$save_title = $wh->{$lc_title}{'save_title'}.' '.$sN;
					$new_ep = $sN;
					# multiple disk seasons (DVDr) only - m can also match multiple seasons s01-04 TODO like multiple eps?
					if ($sh->{$an}{'m'} and $sh->{$an}{'m'} =~ m!^\d$!){ 
						$save_title .= 'd'.$sh->{$an}{'m'}; 
						$new_ep .= 'd'.$sh->{$an}{'m'};
					}
					#&Print ('  '.$save_title.' is on watchlist and not in db (GL02)', 4, 0);
				}
				# "noep" sub_label as label
				elsif (!$sh->{$an}{'sub_label'} and $sh->{$an}{'label'} and $wh->{$lc_title}{'ep'} eq 'noep'){
					&Print ('  '.$save_title.' '.$sh->{$an}{'label'}.' is on watchlist and not in db (GL02)', 4, 0);
					$save_title = $wh->{$lc_title}{'save_title'}.' '.$sh->{$an}{'label'};
					#&Print ('  '.$save_title.' is on watchlist and not in db (GL02)', 4, 0);
					$new_ep = $sh->{$an}{'label'};
				}
				# no label or sub_label, but "none" match
				elsif (!$sh->{$an}{'label'} and !$sh->{$an}{'sub_label'} and $wh->{$lc_title}{'ep'} eq 'none'){
					&Print ('  '.$save_title.' is on watchlist and not in db (GL02)', 4, 0);
					$save_title = $wh->{$lc_title}{'save_title'};
					#&Print ('  '.$save_title.' is on watchlist and not in db (GL02)', 4, 0);
					$new_ep = 'none';
				}
# 				else { # TODO ep, pt, etc.
# 					&Print ('  No watch match found for '.$save_title.' '.$sh->{$an}{'label'}.' (GL02)', 4, 0);
# 					$watch = 0;
# 				}
# 				# s0N has to match above, otherwise we don't want it
# 				elsif ($sN and $sh->{$an}{'label'} eq $sN){
# 					&Print (' '.$save_title.' '.$sh->{$an}{'label'}.' has go (GL02)', 4, 0);
# 					$fetch = 0;
# 				}
				# s0N has to match above, otherwise we don't want it. Don't want anthing else unless AT is set
				elsif (($sN and $sh->{$an}{'label'} eq $sN) or $wh->{$lc_title}{'res'} ne 'AT'){ # need to pass AT to res check for other watch == nums
					&Print ('  No match for '.$save_title.' '.$sh->{$an}{'label'}.' (GL02)', 4, 0);
					$fetch = 0;
				}
				# 12/13 - need full save title for proper AT handling
				elsif ($nnn and $wh->{$lc_title}{'res'} eq 'AT'){
					($f_label, $new_ep) = &FormatLabel ($sh->{$an}{'s'}, $sh->{$an}{'e'}, $sh->{$an}{'m'});
					$save_title = $wh->{$lc_title}{'save_title'}.' '.$f_label;
					if ($VAR{'EpTitle'} and ($sh->{$an}{'sub_label'} or ($sh->{$an}{'sub_label'} = &GetEpTitle ($wh->{$lc_title}{'save_title'}, $sh->{$an}{'s'}, $sh->{$an}{'e'}, $user_agent, $wh->{$lc_title}{'real_title'})))){
						$save_title .= ' - '.$sh->{$an}{'sub_label'};
					}
				}
			}

			# modify if fetch
			$sh->{$an}{'queue'} .= $spaces.'<B class="DEBUG">On Watch List ('.$wh->{$lc_title}{'res'}.')</B>'; #$sh->{$an}{'queue'} .= $spaces.'<B class=\"DEBUG\"><a href="'.$VAR{'WfCgi'}.'?watchlist#TV">On Watch List</a></B>';
		}
		else {
			if ($nnn){
				$sh->{$an}{'queue'} .= "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_watch_form&amp;nt=$enc_nt&amp;la=$sh->{$an}{'label'}&amp;ca=TV&amp;sc=$site\_$cat_name:$an\">Add to Watch List</a>";
			}
			# TODO elsif ($sh->{$an}{'label'} =~ m!^(?:s|e|pt)\d+$!){
			#	$sh->{$an}{'queue'} .= "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_watch_form&amp;nt=$sh->{$an}{'title_enc'}&amp;la=$sh->{$an}{'label'}&amp;ca=TV&amp;sc=$site\_$cat_name:$an\">Add to Watch List</a>";
			#}
			# noep
			elsif ($sh->{$an}{'label'} and $sh->{$an}{'label'} =~ m![\w ]{7,99}! and !$sh->{$an}{'sublabel'}){
				$sh->{$an}{'queue'} .= "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_watch_form&amp;nt=$enc_nt&amp;la=noep&amp;ca=TV&amp;sc=$site\_$cat_name:$an\">Add to Watch List</a>";
			}
			# none
# 			elsif (!$sh->{$an}{'label'} and !$sh->{$an}{'sublabel'}){
# 				$sh->{$an}{'queue'} .= "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_watch_form&amp;nt=$enc_nt&amp;la=none&amp;ca=TV&amp;sc=$site\_$cat_name:$an\">Add to Watch List</a>";
# 			}
			else { $sh->{$an}{'queue'} .= "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_watch_form&amp;nt=$enc_nt&amp;la=&amp;ca=TV&amp;sc=$site\_$cat_name:$an\">Add to Watch List</a>"; }
		}
	}
	elsif ($dst_cat){ 
		#$sh->{$an}{'links'} .= $spaces; # ...removed Details:, left spaces
		$sh->{$an}{'details'} =~ s!Details:!!;
		$sh->{$an}{'queue'} = "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=$dst_cat&amp;sc=$site\_$cat_name:$an\">Queue</a> ";
		if ($VAR{'HoldDir'} and $dst_cat !~ m!hold$! and $dst_cat !~ m!HoldDir$!){
			$sh->{$an}{'queue'} .= " (<a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=hold&amp;sc=$site\_$cat_name:$an\">hold</a>)";
		}
		$sh->{$an}{'queue'} .= "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_title_form&amp;nt=$enc_nt$s_la$enc_sl&amp;ot=$sh->{$an}{'orig_title'}&amp;sc=$site\_$cat_name:$an\">Edit title</a>";
		$watch = 0;
		$sh->{$an}{'db_data'} = ''; # does it make a difference? uninitialized value line 1488
		if ($cat_name eq 'My-Cart' and ($VAR{'NN_Watch'} eq 'Cart' or $VAR{'NN_Watch'} eq 'All')){
			$watch = 1;
			$fetch = 1;
			#$save_title = $sh->{$an}{'title'};
			if ($sh->{$an}{'label'}){ $save_title .= ' '.$sh->{$an}{'label'}; }
			if ($sh->{$an}{'sub_label'}){ $save_title .= ' - '.$sh->{$an}{'sub_label'}; }
		}
	}
	elsif ($VAR{'Categories'}){
		$sh->{$an}{'links'} .= $spaces; # 'details' on links line which is only a site link for all but TV/Movies
		$sh->{$an}{'queue'} = '<br>Queue to: ';
		my @Categories = split (m!\|!, $VAR{'Categories'});
		foreach (@Categories){ 
			$sh->{$an}{'queue'} .= "<a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=$_&amp;sc=$site\_$cat_name:$an\">$_</a> ";
		}
		if ($VAR{'HoldDir'}){
			$sh->{$an}{'queue'} .= " <a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=hold&amp;sc=$site\_$cat_name:$an\">hold</a>";
		}
		$sh->{$an}{'queue'} .= "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_title_form&amp;nt=$enc_nt$s_la$enc_sl&amp;ot=$sh->{$an}{'orig_title'}&amp;sc=$site\_$cat_name:$an\">Edit title</a>";
		$watch = 0;
		$sh->{$an}{'db_data'} = ''; # does it make a difference? uninitialized value line 1488
	}
	else { # just in case (ca=nzb not tested/supported)
		$sh->{$an}{'links'} .= $spaces;
		$sh->{$an}{'queue'} = "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=nzb&amp;sc=$site\_$cat_name:$an\">Queue</a>";
		if ($VAR{'HoldDir'}){
			$sh->{$an}{'queue'} .= " (<a href=\"$VAR{'WfCgi'}?do=$site\_fetch&amp;nt=$enc_nt$s_la$enc_sl&amp;id=$sh->{$an}{'nzb_id'}&amp;ca=hold&amp;sc=$site\_$cat_name:$an\">hold</a>)";
		}
		$sh->{$an}{'queue'} .= "$spaces<a href=\"$VAR{'WfCgi'}?do=$site\_title_form&amp;nt=$enc_nt$s_la$enc_sl&amp;ot=$sh->{$an}{'orig_title'}&amp;sc=$site\_$cat_name:$an\">Edit title</a>";
		$watch = 0;
	}

	# TV or VID... ALL
	# other checks - can't match - passed the watch/res check (fetch = 1)
	if ($watch and $watch < 10 and $fetch){
		$fetch = 0; # <<<<<<<<<<< if no matches it becomes 1 again (can become 2 or 3 in the process of checking)
		# other checks moved to &nzb_tests and done earlier
		if ($watch == 2){ 
			$fetch = 2;
		}
		# get fix match - don't have (13) and it passed all other checks (must include HoldLabel check)
		elsif ($watch == 3){ 
			$fetch = 3;
		}
		else { $fetch = 1; }
		
	}

	#$free = 0;  # for testing = no nzb download
	# ### passed checks, fetch it ###
	#my $message = ; # TODO build message (if got_nzb) for html browse page html head
	if ($fetch and $free and $max_nzbs){ # $max_nzbs = 0 if none left
		my $status;
		my $got_nzb;
		
		if ($fetch == 2){ # hold - new db entry
			$status = $type.'Hold';
			&Print ('  Have '.$type.' Hold Labels match, sending '.$save_title.' to HoldDir (WF42)', 5, 0);
			$got_nzb = &FetchZip ($site, $sh->{$an}{'url'}, $save_title.'.zip', '', 'HoldDir', $user_agent);
		}
		elsif ($fetch == 3){ # get fix > hold (already queued an nzb)
			$status = $dbh->{$lc_title}{$new_ep}; # db ep => id/status (db has separate nnn entries for nnn-nn, is last nnn for new ep OK here
			$status .= '*';
			&Print ('  Have GetFix match, sending '.$save_title.' to HoldDir (WF42)', 5, 0);
			$got_nzb = &FetchZip ($site, $sh->{$an}{'url'}, $save_title.'.zip', '', 'HoldDir', $user_agent);
		}
		elsif ($dst_cat){ # queue - new (1) or overwrite hold (9)
			$status = 'queued';
			&Print ('  Have cat match, sending '.$save_title.' to '.$dst_cat.' (WF42)', 5, 0);
# 			if ($dst_cat !~ m!Sample! and $dst_cat !~ m!hold!i and $VAR{'NzbgetRev'} and $VAR{'NzbgetRev'} > 507 and $site ne 'Nzbmatrix' and $site ne 'Nzbsrus' and ($VAR{'NO_Key'} or $site ne 'Nzbsorg')){
# 				my $p = 0;
# 				if ($wh->{$lc_title}{'priority'} =~ m!(max|high|low|min)!){
# 					$p = $1;
# 					$p =~ s!max!100!;
# 					$p =~ s!high!50!;
# 					$p =~ s!low!-50!;
# 					$p =~ s!min!-100!;
# 				}
# 				if (system qx($VAR{'NzbgetRun'} -A C '$dst_cat' N '$save_title.nzb' I '$p' U '$sh->{$an}{'url'}' > /dev/null)){
# 					&Print ('  Sent -A -C '.$dst_cat.' N '.$save_title.'.nzb I '.$p.' U '.$sh->{$an}{'url'}.'.nzb to nzbget (FN67)', 5, 0);
# 					$got_nzb = 1;
# 					# following moved to page/search update
# # 					if ($VAR{'NzbTrim'}){
# # 						system qx($VAR{'NzbgetRun'} -E FR P \"[_.-]\($VAR{'NzbTrim'}\)\(\b|_|\.|-\)\" > /dev/null);
# # 					}
# 				}
# 				else { &Print ("  Sending queue command to nzbget failed (FN67)", 1, 0); }
# 			}
# 			else { $got_nzb = &FetchZip ($site, $sh->{$an}{'url'}, $save_title.'.zip', $VAR{'NzbDir'}.'/'.$dst_cat, $dst_cat, $user_agent); }
			if ($dst_cat eq 'HoldDir'){
				$fetch = 2;
				$status = 'nzb';
				
			}
			# add got fix flag to new nzb if it matches
			if ($VAR{'GetFix'} and $sh->{$an}{'tail'} =~ m!($VAR{'GetFix'})!i){		
				$status .= '*';
			}
			$got_nzb = &FetchZip ($site, $sh->{$an}{'url'}, $save_title.'.zip', $VAR{'NzbDir'}.'/'.$dst_cat, $dst_cat, $user_agent);
		}
		else { &Print ('  Have no category for '.$save_title.', this should not happen (WF42)', 1, 0); }

		if ($got_nzb){
# 			# -A F queue w/ priority > 508... no real gain yet, wait till get -A U working - > r510
# 			if ($fetch == 1 and $VAR{'NzbgetRev'} and $VAR{'NzbgetRev'} > 507){# and $site ne 'Nzbmatrix' and $site ne 'Nzbsrus' and ($VAR{'NO_Key'} or $site ne 'Nzbsorg')){ 
# 				# moved up and changed to URL queue - -A U... back to -F C I F
# 				my $p = 0;
# 				if ($wh->{$lc_title}{'priority'} =~ m!(max|high|low|min)!){
# 					$p = $1;
# 					$p =~ s!max!100!;
# 					$p =~ s!high!50!;
# 					$p =~ s!low!-50!;
# 					$p =~ s!min!-100!;
# 				}
# 				# need to rename nzb.processed nzb or nzbget will mess the tile up (leave extensions on)
# 				&Save ($VAR{'NzbDir'}.'/'.$dst_cat, $save_title, 'nzb_processed', $VAR{'NzbDir'}.'/'.$dst_cat, $save_title, 'nzb', 'FZ05'); 
# 				if (system qx($VAR{'NzbgetRun'} -A C '$dst_cat' I '$p' F '$VAR{'NzbDir'}/$dst_cat/$save_title.nzb' > /dev/null)){
# 					&Print ('  Sent -A -C '.$dst_cat.' I '.$p.' F '.$VAR{'NzbDir'}.'/'.$dst_cat.'/'.$save_title.'.nzb to nzbget (FN67)', 5, 0);
# 					&Save ($VAR{'NzbDir'}.'/'.$dst_cat, $save_title, 'nzb', $VAR{'NzbDir'}.'/'.$dst_cat, $save_title, 'nzb.queued', 'FZ05'); 
# 				}
# 				else { &Print ("  Sending queue command to nzbget failed (FN67)", 1, 0); }
# 			}
			# -S W queue added in r462
			if ($fetch == 1 and $VAR{'NzbgetRev'} and $VAR{'NzbgetRev'} > 461 and system("$VAR{'NzbgetRun'} -S W > /dev/null") == 0){
				&Print ("  Sent scan command to nzbget (FN67)", 5, 0);
				if ($wh->{$lc_title}{'priority'} =~ m!(max|high|low|min)!){
					my $k = $1;
					my %p = (max => 100, high => 50, low => '-50', min => '-100');
					if (system qx($VAR{'NzbgetRun'} -E GN I '$p{$k}' '$save_title' > /dev/null)){
						&Print ('  Sent '.$wh->{$lc_title}{'priority'}.' priority command to nzbget (SP47)', 5, 0);
					}
				}
				#&monitor;
			} 
			# -A F queue - r442-462
			elsif ($fetch == 1 and $VAR{'NzbgetRev'} and $VAR{'NzbgetRev'} > 442){ 
				# need to rename nzb.processed nzb or nzbget will mess the tile up (leave extensions on)
				&Save ($VAR{'NzbDir'}.'/'.$dst_cat, $save_title, 'nzb_processed', $VAR{'NzbDir'}.'/'.$dst_cat, $save_title, 'nzb', 'FZ05'); 
				if (system qx($VAR{'NzbgetRun'} -A F \"$VAR{'NzbDir'}/$dst_cat/$save_title.nzb\" -K \"$dst_cat\" > /dev/null)){
					&Print ('  Sent -A F '.$VAR{'NzbDir'}.'/'.$dst_cat.'/'.$save_title.'.nzb -K '.$dst_cat.' to nzbget (FN67)', 5, 0);
					&Save ($VAR{'NzbDir'}.'/'.$dst_cat, $save_title, 'nzb', $VAR{'NzbDir'}.'/'.$dst_cat, $save_title, 'nzb.queued', 'FZ05'); 
					# set priority if nzbget > r442
					if ($wh->{$lc_title}{'priority'} =~ m!(max|high|low|min)!){
						my $k = $1;
						my %p = (max => 100, high => 50, low => '-50', min => '-100');
						if (system qx($VAR{'NzbgetRun'} -E GN I '$p{$k}' '$save_title' > /dev/null)){
							&Print ('  Sent '.$wh->{$lc_title}{'priority'}.' priority command to nzbget (WF47)', 5, 0);
						}
					}
				}
				#&monitor;
			}
			# -S queue fallback
			elsif ($fetch == 1 and system("$VAR{'NzbgetRun'} -S > /dev/null") == 0){
				&Print ("  Sent scan command to nzbget (FN67)", 5, 0);
				#&monitor;
			}
			elsif ($fetch == 1) { 
				&Print ("  Sending scan command to nzbget failed (FN67)", 1, 0);
			}
			
			$free --;
			$new_nzbs ++;
			$max_nzbs --;
			#$max_nzbs = $max_nzbs - $new_nzbs;
			&Print ('  Nzbs free left: '.$free.', max left '.$max_nzbs.', new '.$new_nzbs.' (WF46)', 5, 0);
			
			# DATABASE - update db and db hash... add orig_title to db starting r157
			if ($dst_cat){ &UpdateDb ($save_title, $status, $VAR{'DbFile'}, $dst_cat, 'WF44', $sh->{$an}{'orig_title'}); }
			else { &UpdateDb ($save_title, $status, $VAR{'DbFile'}, '', 'WF44', $sh->{$an}{'orig_title'}); }
			# needed for future $dbh checks when new title isn't in $dbh - update db has no effect on $dbh - 3 is old title
			unless ($fetch == 3 or $watch == 9){ 
				unless ($dbh->{$lc_title}{'title'}){
					$dbh->{$lc_title}{'title'} = $wh->{$lc_title}{'save_title'};
					$dbh->{$lc_title}{'type'} = 'OT'; # so Tv and Vid works
					&Print ('  Added '.$save_title.' to db hash (WF46)', 5, 0);
				}
			}
			# add multi ep to db hash as single eps
			if ($sh->{$an}{'m'}){
				my $first_ep = $sh->{$an}{'s'}.$sh->{$an}{'e'};
				my $last_ep = $sh->{$an}{'s'}.$sh->{$an}{'m'};
				while ($first_ep <= $last_ep){ 
					$dbh->{$lc_title}{$first_ep} = $status;
					&Print ('  Added '.$dbh->{$lc_title}{$first_ep}.' flag (for '.$first_ep.') to db hash (WF46)', 5, 0);
					$first_ep ++;
				}
			}
			else {
				$dbh->{$lc_title}{$new_ep} = $status; 
				&Print ('  Added '.$dbh->{$lc_title}{$new_ep}.' flag to db hash (WF46)', 5, 0);
			}
						
			# HOLD DIR edits
			# fetch type 1 hold delete/add, if appropriate
			if ($fetch == 1){ 
				$sh->{$an}{'got'} = 'got new nzb'; 
				# if there's a matching nzb on hold (9), delete it and its hold.txt entry
				if (-e "$VAR{'HoldDir'}/$save_title.nzb"){
					&Delete ($VAR{'HoldDir'}, $save_title.'.nzb', 'WF44');
					local ($^I, @ARGV) = ('.bak', $VAR{'DataDir'}.'/ppweb_hold.txt');
					while(<>){
						if (m!^$save_title\t!){ 
							&Print ('  Deleted old '.$save_title.' hold.txt entry (WF46)', 5, 0);
							next; 
						}
						else { print; }
					}
				}
				# add hold.txt entry for samples - may follow Tv or Vid Hold entry removal so it can't be elsif
				if ($dst_cat =~ m!/Sample$!){ # second hold.txt write
					my $links = $sh->{$an}{'links'};
					$links =~ s!re=[^"]+!re=hold:$sh->{$an}{'a_name'}!g;
					open (WHTH, ">>$VAR{'DataDir'}/ppweb_hold.txt") or &Print ("  Couldn't open $VAR{'DataDir'}/ppweb_hold.txt, $! (118)", 1, 1);
					print WHTH "$save_title	<P><A NAME=\"$sh->{$an}{'a_name'}\"><B class=\"INFO\">$save_title</B></A>&nbsp;&nbsp;&nbsp;$sh->{$an}{'tail'}<br>$links$sh->{$an}{'details'} <br>Db search: <A HREF=\"$VAR{'DbCgi'}?do=search_db&amp;kw=$save_title&amp;re=hold:$sh->{$an}{'a_name'}\">$save_title</A><br>\n";
					close WHTH or warn $!;
					&Print ('  Wrote '.$save_title.' hold.txt entry (WF46)', 5, 0);
				}
			}
			# fetch type 2 + 3 hold.txt entry
			else {
				$sh->{$an}{'got'} = 'nzb > hold'; 
				
				# Basically the same as in SiteFetch (wfnzb.cgi) TODO sub and expand, e.g. NN_Cats
				my $queue_links = '';
				if ($type eq 'Tv' or $type eq 'Vid'){
					my $q_cat = $VAR{$type.'Nzbs'};
					$q_cat =~ s!/Sample$!!;
					if ($q_cat eq 'HoldDir'){
						$queue_links = 'Queue to: ';
						my @Categories = split (m!\|!, $VAR{'Categories'});
						foreach (@Categories){ 
							$queue_links .= '<a href="'.$VAR{'WfCgi'}.'?hold_queue%20'.$save_title.'.nzb:'.$_.'">'.$_.'</a>&nbsp;&nbsp;&nbsp;';
						}
					}
					else {
						$queue_links = '<a href="'.$VAR{'WfCgi'}.'?hold_queue%20'.$save_title.'.nzb:'.$q_cat.'">Queue</a>';
						if (-e "$VAR{'NzbDir'}/$q_cat/Sample"){
							$queue_links .= ' (<a href="'.$VAR{'WfCgi'}.'?hold_queue%20'.$save_title.'.nzb:'.$q_cat.'/Sample">sample</a>)';
							# made dir optional in hold_queue so $VAR{'HoldDir'} not needed in link
							#$queue_links .= " (<a href=\"$VAR{'WfCgi'}?hold_queue%20$VAR{'HoldDir'}/$var{'nt'}.nzb:$q_cat/Sample\">sample</a>)";
						}
						$queue_links .= '&nbsp;&nbsp;&nbsp;';
					}
				}
				
				# add hold.txt entry
				open (WHTH, ">>$VAR{'DataDir'}/ppweb_hold.txt") or &Print ("  Couldn't open $VAR{'DataDir'}/ppweb_hold.txt, $! (118)", 1, 1);
				my $links = $sh->{$an}{'links'};
				$links =~ s!re=[^"]+!re=hold:$sh->{$an}{'a_name'}!g;
				print WHTH "$save_title	<P><A NAME=\"$sh->{$an}{'a_name'}\"><B class=\"INFO\">$save_title</B></A>&nbsp;&nbsp;&nbsp;$sh->{$an}{'tail'}<br>$links$sh->{$an}{'details'} <br>Db search: <A HREF=\"$VAR{'DbCgi'}?do=search_db&amp;kw=$save_title&amp;re=hold:$sh->{$an}{'a_name'}\">$save_title</A><br>$queue_links\n";
				close WHTH or warn $!;
				&Print ('  Wrote '.$save_title.' hold.txt entry (WF46)', 5, 0);
			}
			&Print ('  Got nzb, appending message (GLM)', 5, 0);
			$message .= "$save_title <br>";
			# WATCH LIST edits TODO sN deletion
			# update watchlist if nnn ep and nnn ep is > watchlist ep - only new wanted eps (1), not hold (2), fix (3) or cart (4)
			if ($type eq 'Tv' and $watch == 1 and $new_ep =~ m!^\d+$! and $new_ep > $wh->{$lc_title}{'ep'}){
				# update watchlist
				if ($fetch == 1 or $fetch == 2){ # added 2 so hold nzbs update watch list - how did they get past db check?
					my $found = 0;
					open (WTXT, ">$VAR{'WatchFile'}.tmp") or die $!;
					open (RTXT, "<$VAR{'WatchFile'}") or die $!;
					while (<RTXT>){
						if (m!^(\Q$wh->{$lc_title}{'real_title'}\E[^\t]*)\t$wh->{$lc_title}{'ep'}\t$wh->{$lc_title}{'res'}\t($wh->{$lc_title}{'priority'}\t)?$wh->{$lc_title}{'save_title'}$!i){
							if ($2){ # priority
								print WTXT "$1\t$new_ep\t$wh->{$lc_title}{'res'}\t$2$wh->{$lc_title}{'save_title'}\n";
							}
							else {
								print WTXT "$1\t$new_ep\t$wh->{$lc_title}{'res'}\tnorm\t$wh->{$lc_title}{'save_title'}\n";
							}
							$found = 1; # reuse, was 0 or we wouldn't be here
						}
						else { print WTXT; }
					}
					close WTXT or warn $!;
					rename ("$VAR{'WatchFile'}.tmp", "$VAR{'WatchFile'}") or die $!;		
					close RTXT or warn $!;
					if ($found){ &Print ("  Updating watchlist: $save_title $wh->{$lc_title}{'ep'} to $new_ep (WF46)", 5, 0); }
					else { &Print ("  Updating watchlist failed for: $save_title $new_ep (WF46)", 1, 0); }
				}
				
				# update watch hash with new (> old) ep so watch.txt can be updated with any additional (> this) eps
				$wh->{$lc_title}{'ep'} = $new_ep;
			}
			# any new movie queue. AL could allow multiple res grabs
			elsif ($type eq 'Vid' and ($fetch == 1 or $fetch == 2)){#$wh->{$lc_title}{'res'} ne 'AL'){
			
				# comment out watch entry
				open (WTXT, ">$VAR{'WatchFile'}.tmp") or die $!;
				open (RTXT, "<$VAR{'WatchFile'}") or die $!;
				while (<RTXT>){
					s!^(\Q$wh->{$lc_title}{'real_title'}\E[^\t]*)!# queued $1!;
					print WTXT;
				}
				close WTXT or warn $!;
				rename ("$VAR{'WatchFile'}.tmp", "$VAR{'WatchFile'}") or die $!;		
				close RTXT or warn $!;
				
				# delete wh entry so On Watch List won't get printed on future title matches
				delete $wh->{$lc_title};
				&Print ('  Deleted '.$save_title.' from watch hash (WF46)', 5, 0);
				
				# modify watch hash - same site dupe prevention
				# can modify first title, but not save title - needed for hold.txt
				#$wh->{$lc_title}{'real_title'} = 'got_nzb';
				#&Print ("  Setting watch hash to got_nzb for $save_title (WF34)", 5, 0);
				# the following will find the above during checks
				#if ($wh->{$lc_title}{'real_title'} eq 'got_nzb'){
				#	&Print ("  Have watch hash got_nzb flag for $wh->{$lc_title}{'save_title'}, skipping (WF02)", 5, 0);
				#}
			}
			
		}
	}
	elsif ($fetch){
		unless ($free){ &Print ("  No free nzbs left for $site, skipping $save_title (WF46)", 3, 0); }
		unless ($max_nzbs){ &Print ("  MaxNzbs limit ($VAR{'MaxNzbs'}) reached, skipping $save_title (WF46)", 3, 0); }
	}
	return ($sh, $free, $new_nzbs, $max_nzbs, $message);
}

# sub monitor {
# 	if ($VAR{'Monitor'} and !-e "$VAR{'DataDir'}/monitor.lock"){
# 		my $pid = system qx(nohup $VAR{'ScriptDir'}/ppweb_monitor.pl > /dev/null 2>&1 &);
# 		if ($pid){
# 			open(WF, '>', $VAR{'DataDir'}.'/monitor.lock') or die ("$!");
# 			print WF $pid;
# 			close (WF) or warn $!;
# 		}
# 		else { &Print ("  Starting the monitor script failed (SP67)", 1, 0); }
# 	}
# }

sub nzb_tests {
	#my ($title, $size, $age, $tail, $max_nzbs, $skip_group, $skip_poster, $complete) = @_;
	my ($title, $max_nzbs, $an, $sh) = @_;
	#$sh->{$an}{'size'}, $sh->{$an}{'age'}, $sh->{$an}{'tail'}, $sh->{$an}{'group'}, $sh->{$an}{'poster'}, $sh->{$an}{'complete'});

	my $fetch = 0; # becomes 1 if passes checks
	# max nzbs
	unless ($max_nzbs){
		&Print ('  MaxNzbs limit ('.$VAR{'MaxNzbs'}.') reached, skipping '.$title.' (NT01)', 3, 0);
	}
	# skip poster
	elsif ($VAR{'SkipPoster'} and $sh->{$an}{'poster'} =~ m!($VAR{'SkipPoster'})!i){
		&Print ('  '.$title.' has a '.$1.' SkipPoster match, skipping (NT08)', 3, 0);
	}
	# size
	elsif ($sh->{$an}{'size'} and $VAR{'MaxSize'} and $sh->{$an}{'size'} > $VAR{'MaxSize'}){
		&Print ('  '.$title.' is too big - '.$sh->{$an}{'size'}.' > '.$VAR{'MaxSize'}.' (MaxSize), skipping (NT02)', 3, 0);
	}
	elsif ($sh->{$an}{'size'} and $VAR{'MinSize'} and $sh->{$an}{'size'} < $VAR{'MinSize'}){
		&Print ('  '.$title.' is too small - '.$sh->{$an}{'size'}.' < '.$VAR{'MinSize'}.' (MinSize), skipping (NT03)', 3, 0);
	}
	# age
	elsif ($sh->{$an}{'age'} and (($VAR{'MaxAge'} and $sh->{$an}{'age'} > $VAR{'MaxAge'}) or (!$VAR{'MaxAge'} and $sh->{$an}{'age'} > 1))){
		&Print ('  '.$title.' is too old - '.$sh->{$an}{'age'}.' > '.$VAR{'MaxAge'}.' (MaxAge), skipping (NT04)', 3, 0);
	}
	# skip labels
	elsif ($VAR{'SkipLabels'} and $sh->{$an}{'tail'} =~ m!\b($VAR{'SkipLabels'})\b!i){
		&Print ('  '.$title.' has a '.$1.' SkipLabels match, skipping (NT05)', 3, 0);
	}
	# skip lang
	elsif ($VAR{'SkipLang'} and $sh->{$an}{'tail'} =~ m!\b($VAR{'SkipLang'})\b!i){
		&Print ('  '.$title.' has a '.$1.' SkipLang match, skipping (NT06)', 3, 0);
	}
	# skip group
	elsif ($VAR{'SkipGroup'} and $sh->{$an}{'group'} =~ m!\b($VAR{'SkipGroup'})\b!i){
		&Print ('  '.$title.' has a '.$1.' SkipGroup match, skipping (NT07)', 3, 0);
	}
	# skip incompletes
	elsif ($VAR{'SkipIncomplete'} and $sh->{$an}{'complete'} and $sh->{$an}{'complete'} < $VAR{'SkipIncomplete'}){
		&Print ('  '.$title.' is only '. $sh->{$an}{'complete'}.'percent complete, skipping (NT09)', 3, 0);
	}
# 	unless ($max_nzbs){
# 		&Print ('  MaxNzbs limit ('.$VAR{'MaxNzbs'}.') reached, skipping '.$title.' (NT01)', 3, 0);
# 	}
# 	# size
# 	elsif ($size and $VAR{'MaxSize'} and $size > $VAR{'MaxSize'}){
# 		&Print ('  '.$title.' is too big - '.$size.' > '.$VAR{'MaxSize'}.' (MaxSize), skipping (NT02)', 3, 0);
# 	}
# 	elsif ($size and $VAR{'MinSize'} and $size < $VAR{'MinSize'}){
# 		&Print ('  '.$title.' is too small - '.$size.' < '.$VAR{'MinSize'}.' (MinSize), skipping (NT03)', 3, 0);
# 	}
# 	# age
# 	elsif ($age and (($VAR{'MaxAge'} and $age > $VAR{'MaxAge'}) or (!$VAR{'MaxAge'} and $age > 1))){
# 		&Print ('  '.$title.' is too old - '.$age.' > '.$VAR{'MaxAge'}.' (MaxAge), skipping (NT04)', 3, 0);
# 	}
# 	# skip labels
# 	elsif ($VAR{'SkipLabels'} and $tail =~ m!\b($VAR{'SkipLabels'})\b!i){
# 		&Print ('  '.$title.' has a '.$1.' SkipLabels match, skipping (NT05)', 3, 0);
# 	}
# 	# skip lang
# 	elsif ($VAR{'SkipLang'} and $tail =~ m!\b($VAR{'SkipLang'})\b!i){
# 		&Print ('  '.$title.' has a '.$1.' SkipLang match, skipping (NT06)', 3, 0);
# 	}
# 	# skip group
# 	elsif ($VAR{'SkipGroup'} and $skip_group =~ m!\b($VAR{'SkipGroup'})\b!i){
# 		&Print ('  '.$title.' has a '.$1.' SkipGroup match, skipping (NT07)', 3, 0);
# 	}
# 	# skip poster
# 	elsif ($VAR{'SkipPoster'} and $skip_poster =~ m!\b($VAR{'SkipPoster'})\b!i){
# 		&Print ('  '.$title.' has a '.$1.' SkipPoster match, skipping (NT08)', 3, 0);
# 	}
# 	# skip incompletes
# 	elsif ($complete and $complete < 100){
# 		&Print ('  '.$title.' is only '. $complete.'percent complete, skipping (NT09)', 3, 0);
# 	}
# 	# skip poster
# 	elsif ($VAR{'WhiteList'} and $skip_poster =~ m!\b($VAR{'SkipPoster'})\b!i){
# 		&Print ('  '.$title.' has a '.$1.' SkipPoster match, skipping (NT08)', 3, 0);
# 	}
	else {	$fetch = 1; }
	return $fetch;
}

sub hold_tests {
	my ($save_title, $label, $value) = @_;
	my $watch = 10;
	# check to see if database ep id = TvHold - need ep in db format for nnn, others (sN dd-dd-dd) should match listing format
	if ($value eq 'TvHold'){ # ep/nnn = id/TvHold
		$watch = 9; # < 10 = fetch 1 unless fails TvHoldLabels check later
		&Print ('  Db has TvHold match for '.$save_title.' (GLT1)', 5, 0);#.' '.$label < should be in save title and shouldn't need to pass label
	}
	# check to see if database ep id = VidHold
	elsif ($value eq 'VidHold'){ # ep/nnn = id/TvHold
		$watch = 9; # < 10 = fetch 1 unless fails VidHoldLabels check later
		&Print ('  Db has VidHold match for '.$save_title.' (GLT1)', 5, 0);
	}
	# check to see if database ep id = <status>* - status could be queued, got, etc.
	elsif ($value =~ m!\*$!){
		&Print ('  Db has got fix flag ('.$value.') for '.$save_title.' (GLT1)', 5, 0);
		$watch = 13; # already have/had get fix nzb
	}
	return $watch;
}
	
sub Write_New {
	my ($sh, $site, $cat_num, $default, $free, $menu, $keyword, $cat_name, $message) = @_;
	my @new_nzbs;
	#my $new_cnt = 0;
	# $cat_num can be multiple cats - used here for page name and to write search form
	# when is cat name empty?
	# searches from configured cats need cat name rewritten (and cat num will be a single number)
	# need to do this earlier... done
	#if (!$cat_name or ($cat_num !~ m!,! and $cat_name ne $Sites{$site}{$cat_num})){
	# shouldn't be needed anymore
	unless ($cat_name){
		$cat_name = $Sites{$site}{$cat_num};#&CatName ($cat_num);
		&Print ("  Didn't have cat name ($cat_name), this shouldn't happen (WN01)", 2, 0);
	}
	my $html_name = "$site\_$cat_name";
	# ### my $page_name = $site.' '.$cat_name;
# 	if ($keyword){ # search results pages
# 		$html_name = "$site\_search_$cat_name"; 
# 		$page_name = $site.' search '.$cat_name;
# 	}
	
	my @old_ids;
	# manual updates - gray everything from the last update
	if (!$keyword and !$ARGV[0] and -e "$VAR{'HtmlDir'}/$html_name.html"){
		open (RHTM, "<$VAR{'HtmlDir'}/$html_name.html") or die $!;
		while (<RHTM>){
			if (m!^<P><A NAME.+?id=([^&]+)&!){ # non greedy first match
				push (@old_ids, $1);
			}
		}
		close RHTM or warn $!;
	}
	# auto updates - retain existing greyed markup (no new greyed entries)
	elsif (@ARGV and $ARGV[0] eq 'nzbget_task' and -e "$VAR{'HtmlDir'}/$html_name.html"){
		open (RHTM, "<$VAR{'HtmlDir'}/$html_name.html") or die $!;
		while (<RHTM>){
			if (m!^<P><A NAME[^>]+><B class="DEBUG">.+?id=([^&]+)&!){
				push (@old_ids, $1);
			}
		}
		close RHTM or warn $!;
	}
	# otherwise its a new page and we need to update all side menus
	else { $new_page = 1; }
		
	open (HTM, ">$VAR{'HtmlDir'}/$html_name.html") or die $!;

	#my $related_links = &HtmRelated ($site.' '.$cat_name, $site);
	my $related_links = &HtmRelated ($cat_name, $site);
	# second is message
	print HTM &HtmHead ($site.' '.$cat_name, $message, $VAR{'HomeUrl'}, "Return to $VAR{'HomeName'}", $related_links);
	
	if ($free < 11 and $default){
		#my $default = $VAR{"$XX\_Default"}; # should pass default - only place XX is used
		if ($html_name =~ m!$default!){ 
			print HTM "<P>Downloads left: $free</P>\n";
			$free = 99; # last use above, prevents re-editing this page
		}
	}
	
	my $scat = $cat_name;
	$scat =~ s!^search_!!; # don't want search_ in search form
	# after this cat is used for nzb fetch links... WAS used
# 	if ($site eq 'Kerews'){
# 		&KerewsSearchForm ($site, $cat_num, $scat, $keyword); 
# 	}
	if ($site eq 'Nzbsorg'){
		&NzbsorgSearchForm ($site, $cat_num, $scat, $keyword); 
	}
	else {
		&SiteSearchForm ($site, $cat_num, $scat, $keyword); 
	}
	#}
	# prepend search flag so fetch knows what page to return to
	# if ($keyword){ $cat_num = "search_$cat_num"; } ... $sh now comes in w links
	
	#my @sortorder = sort keys %hash;
	#foreach my $key (@sortorder)	
	
	if ($sh->{1}{'orig_title'} eq 'Failed'){
		print HTM qq~<P>$sh->{1}{'details'}</P>~;
	}
	elsif ($sh->{1}{'title'}){
		#my $seen;
		# grabs high to low
		#foreach my $an ( sort { $sh->{$b}{'grabs'} <=> $sh->{$a}{'grabs'} } keys %$sh){
		# size low to high
		#foreach my $an ( sort { $sh->{$a}{'size'} <=> $sh->{$b}{'size'} } keys %$sh){
		# new to old
		foreach my $an (sort { $a <=> $b } keys %$sh ) { 
			my $title_class = 'INFO'; # default, gets switched by db lookups
			# where could this get set?, its not set in newznab.pm
			if ($sh->{$an}{'class'}){ $title_class = $sh->{$an}{'class'}; }
			# grey it out if its a previously seen listing
			if (@old_ids){ # empty if writing a new page
				foreach my $id (@old_ids) {
					if ($sh->{$an}{'nzb_id'} and $id eq $sh->{$an}{'nzb_id'}){ 
						$title_class = 'DEBUG';
						# setting here for popular sort later
						$sh->{$an}{'class'} = 'DEBUG';
						#$seen ++;
						last;
					}
				}
			}
			
			# why merge? ... to encode the full title
			if ($sh->{$an}{'label'}){ 
				$sh->{$an}{'title'} .= ' '.$sh->{$an}{'label'};
			}
			if ($sh->{$an}{'sub_label'}){ 
				$sh->{$an}{'title'} .= ' - '.$sh->{$an}{'sub_label'};
			}

			# write entry
			# special case - $sh->{99} in newznab pm
			if ($sh->{$an}{'orig_title'} eq 'pagination'){ 
				if ($keyword){ # only want to handle this title on search returns
					my $matches = $sh->{$an}{'got'};
					my $pages = $matches / 50;
					if ($pages =~ s!\.\d+!!){
						$pages ++;
					}
					print HTM qq~<P>Your search has $matches matches ($pages pages).<br>Note: each page (prev/next click) equals an API hit.<br>Hint: If you want a particular season, search for 'Show Snn' (nn = 01-99).<br><br>~;
					# if we don't remove search_ it will use $cat_num(s) instead of name, we don't want that with TV and Movies
					my $cn = $cat_name;
					$cn =~ s!search_!!;
					# if we have an offset we are past the first page of results
					if ($sh->{$an}{'details'}){
						my $offset = $sh->{$an}{'details'};
						# $offset is start of current page, add 50 to see if we have a next page
						# e.g. 101 > (50 + 50), i.e. there's a third page with a single return
						# we always have a previous page
						if ($matches > ($offset + 50)){
							my $plus_offset = $offset + 50;
							my $minus_offset = $offset - 50;
							print HTM qq~
							<a href="$VAR{'WfCgi'}?do=$site\_search&amp;cn=$cn&amp;kw=$keyword&amp;sc=$cat_num&amp;np=$minus_offset">Previous</A>&nbsp;&nbsp;&nbsp;
							<a href="$VAR{'WfCgi'}?do=$site\_search&amp;cn=$cn&amp;kw=$keyword&amp;sc=$cat_num&amp;np=$plus_offset">Next</A>
							</P>~;
						}
						# last page ($matches < ($offset + 50)) - e.g. 100 !> (50+50), i.e. no 3rd page
						else {
							my $minus_offset = $offset - 50;
							print HTM qq~
							<a href="$VAR{'WfCgi'}?do=$site\_search&amp;cn=$cn&amp;kw=$keyword&amp;sc=$cat_num&amp;np=$minus_offset">Previous</A>
							</P>~;
						}
					}
					# first page (no $offset)
					else {
						print HTM qq~
						<a href="$VAR{'WfCgi'}?do=$site\_search&amp;cn=$cn&amp;kw=$keyword&amp;sc=$cat_num&amp;np=50">Next</A>
						</P>~;
					}
				}
			}
			elsif ($sh->{$an}{'got'}){
				$title_class = 'DEBUG'; # could we use/set hash class?
				$sh->{$an}{'title'} =~ s! !&nbsp;!g; # hack for explorer 5? - line broken title
				# old print line
				#print HTM qq~<P><A NAME="$sh->{$an}{'a_name'}" TITLE="$sh->{$an}{'orig_title'}"><B class="$title_class">$sh->{$an}{'title'}</B></A>&nbsp;&nbsp;&nbsp;$sh->{$an}{'tail'}<br>$sh->{$an}{'links'}$sh->{$an}{'details'}$sh->{$an}{'queue'}&nbsp;&nbsp;&nbsp;<B class="DEBUG">$sh->{$an}{'got'}</B>$sh->{$an}{'db_data'}&nbsp;&nbsp;&nbsp;<A HREF="#top">top</A></P>\n~;
				my $entry = '<P><A NAME="'.$sh->{$an}{'a_name'}.'" TITLE="'.$sh->{$an}{'orig_title'}.'"><B class="'.$title_class.'">'.$sh->{$an}{'title'}.'</B></A>&nbsp;&nbsp;&nbsp;'.$sh->{$an}{'tail'}.'<br>'.$sh->{$an}{'links'}.$sh->{$an}{'details'}.$sh->{$an}{'queue'}.'&nbsp;&nbsp;&nbsp;<B class="DEBUG">'.$sh->{$an}{'got'}.'</B>'.$sh->{$an}{'db_data'}.'&nbsp;&nbsp;&nbsp;<A HREF="#top">top</A></P>'."\n";
				#my $entry = "<P><A NAME=\"$new_cnt\" TITLE=\"$sh->{$an}{'orig_title'}\"><B class=\"$title_class\">$sh->{$an}{'title'}</B></A>&nbsp;&nbsp;&nbsp;$sh->{$an}{'tail'}<br>$sh->{$an}{'links'}$sh->{$an}{'details'}$sh->{$an}{'queue'}&nbsp;&nbsp;&nbsp;<B class=\"DEBUG\">$sh->{$an}{'got'}</B>$sh->{$an}{'db_data'}&nbsp;&nbsp;&nbsp;<A HREF=\"#top\">top</A></P>\n";
				print HTM $entry;
				#$new_cnt++;
				# modify a name links for index.html
				#$entry =~ s!([:"])$sh->{$an}{'a_name'}"!$1$new_cnt"!g;
				push (@new_nzbs, $entry)
				# same as above w/ \"... trying $entry instead
				#push (@new_nzbs, "<P><A NAME=\"$new_cnt\" TITLE=\"$sh->{$an}{'orig_title'}\"><B class=\"$title_class\">$sh->{$an}{'title'}</B></A>&nbsp;&nbsp;&nbsp;$sh->{$an}{'tail'}<br>$sh->{$an}{'links'}$sh->{$an}{'details'}$sh->{$an}{'queue'}&nbsp;&nbsp;&nbsp;<B class=\"DEBUG\">$sh->{$an}{'got'}</B>$sh->{$an}{'db_data'}&nbsp;&nbsp;&nbsp;<A HREF=\"#top\">top</A></P>\n");
			}
			else { 
				$sh->{$an}{'title'} =~ s! !&nbsp;!g;#<A TITLE="
				print HTM qq~<P><A NAME="$sh->{$an}{'a_name'}" TITLE="$sh->{$an}{'orig_title'}"><B class="$title_class">$sh->{$an}{'title'}</B></A>&nbsp;&nbsp;&nbsp;$sh->{$an}{'tail'}<br>$sh->{$an}{'links'}$sh->{$an}{'details'}$sh->{$an}{'queue'}$sh->{$an}{'db_data'}&nbsp;&nbsp;&nbsp;<A HREF="#top">top</A></P>\n~;
				#print HTM qq~<P><A NAME="$sh->{$an}{'a_name'}" TITLE="$sh->{$an}{'orig_title'}"><B class="$title_class">$sh->{$an}{'title'}</B></A>&nbsp;&nbsp;&nbsp;$sh->{$an}{'tail'}<br>$sh->{$an}{'links'}$sh->{$an}{'details'}&nbsp;&nbsp;&nbsp;<A HREF="#top">top</A></P>\n~;
			}
		}
		# its only listings marked as seen, so its useless for actual new VS old
		#if ($seen and $seen > 5){ &Print ("  update includes $seen old listings (FN23)", 4, 0); }
		#elsif ($seen and $seen <= 5){ &Print ("  update includes $seen old listings (FN23)", 2, 0); }
		
		#if (!$keyword and $VAR{'PPWebDir'} =~ m!(.+/ppweb)/ppweb! and -w "$1/index.html"){
		#if (!$keyword and -w $VAR{'HtmlDir'}.'/popular.html'){
			#my $index = $1.'/index.html';
		if (!$keyword and $cat_name =~ m!(TV|Movies)!){
			my $pop_page;
# 			if (-w $VAR{'HtmlDir'}.'/popular.html'){
# 				$pop_page = $VAR{'HtmlDir'}.'/popular.html';
# 			}
			if ($VAR{'PPWebDir'} =~ m!(.+)/ppweb! and -w "$1/index.html"){
				$pop_page = $1.'/index.html';
			}
			if ($pop_page){
				my $prnt_line;
				my $title_class = 'INFO'; # default, gets switched by db lookups
				#&Print ('  index.html found/writable (NI1)', 5, 0);
				my $top_pop = 10;
				open (WTXT, ">$pop_page.tmp") or die $!;
				open (RTXT, "<$pop_page") or die $!;
				while (<RTXT>){
					if (/^<!--$site\_$cat_name-->/ and $VAR{$Sites{$site}{'XX'}.'_Enable'} == 1){
					#if (/^<!--$site\_$cat_name-->/ and $VAR{$Sites{$site}{'XX'}.'_Enable'} == 1){
						#&Print ('  got line match for '.$site.' (NI2)', 5, 0);
						$prnt_line .= "<!--$site\_$cat_name--><P><B>$site $cat_name</B><br>";
						foreach my $an ( sort { $sh->{$b}{'grabs'} <=> $sh->{$a}{'grabs'} } keys %$sh){
							unless ($top_pop){
								#&Print ('  top_pop is empty (NI2)', 5, 0);
								$prnt_line .= '</P>'."\n";
								print WTXT $prnt_line;
								last;
							}
							elsif ($top_pop and $sh->{$an}{'grabs'} > 1){
								if ($sh->{$an}{'class'} and $sh->{$an}{'class'} eq 'DEBUG'){ $title_class = 'DEBUG'; }
								elsif ($sh->{$an}{'got'}){ $title_class = 'DEBUG'; }
								$prnt_line .= '<A HREF="'.$VAR{'HtmlUrl'}.'/'.$html_name.'.html#'.$sh->{$an}{'a_name'}.'"><B class="'.$title_class.'">'.$sh->{$an}{'title'}.'</B></A>&nbsp;&nbsp;'.$sh->{$an}{'tail'}.'&nbsp;&nbsp;&nbsp;('.$sh->{$an}{'grabs'}.')<br>';
								if ($sh->{$an}{'queue'} =~ m!>On Watch List \(!){
									$prnt_line =~ s!<br>$!&nbsp;&nbsp;&nbsp;OWL<br>!;
								}
								$title_class = 'INFO';
								$top_pop --;
							}
						}
						# less than 10 nzbs w/ > 1 grab
						if ($top_pop){
							$prnt_line .= '</P>'."\n";
							print WTXT $prnt_line;
						}
					}
					elsif (/^<!--side_menu-->/){
	# 					my $m = $menu;
	# 					$m =~ s!<A HREF="$VAR{'HomeUrl'}index.html">PPWeb</A>!<B class="DEBUG">PPWeb</B>!;
	# 					$m =~ s!<A HREF="$VAR{'HtmlUrl'}/popular.html">Popular</A>!<B class="DEBUG">Popular</B>!;
	# 					#$m =~ s!NAME="kw" value=""><input type="submit" value="db"></form></div>!NAME="kw" value=""><INPUT TYPE="hidden" NAME="re" value="index\.html"><input type="submit" value="db"></form></div>!;
	# 					#$m =~ s!\.log">!.log&amp;re=popular">!g;
	# 					print WTXT $m;
						print WTXT "$menu\n";
					}
					elsif (/^<!--([^_]+)_([^>]+)-->.+/ and $VAR{$Sites{$1}{'XX'}.'_Enable'} != 1){
						print WTXT "<!--$1_$2-->\n";
					}
					else { print WTXT; }
				}
				close WTXT or warn $!;
				rename ($pop_page.'.tmp', $pop_page) or die $!;		
				close RTXT or warn $!;
			}
		}
	}
	else { print HTM qq~<P>Hash parsing error</P>~; }
	#my $menu = &HtmlMenu;
	# ### if ($keyword){ $cat_name = "search_$cat_name"; }
	# remove link and grey current page
	$menu =~ s!<A HREF="$VAR{'HtmlUrl'}/$site\_$cat_name\.html">$cat_name</A>!<B class="DEBUG">$cat_name</B>!;
	# add(change?) re value to db search form
	#$menu =~ s!NAME="kw" value="">(<INPUT TYPE="hidden" NAME="re" value="[^."]+\.html">)?<input type="submit" value="Find"></form></div>$!NAME="kw" value=""><INPUT TYPE="hidden" NAME="re" value="$site\_$cat_name\.html"><input type="submit" value="Find"></form></div>!;
	$menu =~ s!NAME="kw" value=""><input type="submit" value="db"></form></div>!NAME="kw" value=""><INPUT TYPE="hidden" NAME="re" value="$site\_$cat_name\.html"><input type="submit" value="db"></form></div>!;
	print HTM &HtmFoot ($VAR{'HomeUrl'}, "Return to $VAR{'HomeName'}", $menu);
	close (HTM) or warn $!;
	#&Print ("  Updated $html_name.html (FN24)", 4, 0);
	return @new_nzbs;
}

1;
